From e98f16d35fa7744097e15788fa6f9a54391ea3d8 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 16:54:15 +0200 Subject: [PATCH 01/25] make: rename install_prefix -> DESTDIR --- driver/Makefile.in | 130 ++++++++++++++++++++-------------------- hacks/Makefile.in | 38 ++++++------ hacks/fonts/Makefile.in | 10 ++-- hacks/glx/Makefile.in | 32 +++++----- po/Makefile.in.in | 14 ++--- 5 files changed, 111 insertions(+), 113 deletions(-) diff --git a/driver/Makefile.in b/driver/Makefile.in index a013b82db..edae8cf01 100644 --- a/driver/Makefile.in +++ b/driver/Makefile.in @@ -10,7 +10,7 @@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = .. -install_prefix = +DESTDIR = prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ @@ -315,30 +315,30 @@ install-strip: $(MAKE2) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install install-program:: $(EXES) - @if [ ! -d $(install_prefix)$(bindir) ]; then \ - $(INSTALL_DIRS) $(install_prefix)$(bindir) ; \ + @if [ ! -d $(DESTDIR)$(bindir) ]; then \ + $(INSTALL_DIRS) $(DESTDIR)$(bindir) ; \ fi ; \ - if [ ! -d $(install_prefix)$(HACKDIR) ]; then \ - $(INSTALL_DIRS) $(install_prefix)$(HACKDIR) ; \ + if [ ! -d $(DESTDIR)$(HACKDIR) ]; then \ + $(INSTALL_DIRS) $(DESTDIR)$(HACKDIR) ; \ fi install-program:: $(EXES) @inst="$(INSTALL_PROGRAM)" ; \ for exe in $(EXES); do \ - echo $$inst $$exe $(install_prefix)$(bindir)/$$exe ; \ - $$inst $$exe $(install_prefix)$(bindir)/$$exe ; \ + echo $$inst $$exe $(DESTDIR)$(bindir)/$$exe ; \ + $$inst $$exe $(DESTDIR)$(bindir)/$$exe ; \ done install-program:: $(UTIL_EXES) @inst="$(INSTALL_PROGRAM)" ; \ for exe in $(UTIL_EXES); do \ - echo $$inst $$exe $(install_prefix)$(HACKDIR)/$$exe ; \ - $$inst $$exe $(install_prefix)$(HACKDIR)/$$exe ; \ + echo $$inst $$exe $(DESTDIR)$(HACKDIR)/$$exe ; \ + $$inst $$exe $(DESTDIR)$(HACKDIR)/$$exe ; \ done install-program:: $(SETUID_EXES) @inst="$(INSTALL_PROGRAM)" ; \ - idir="$(install_prefix)$(HACKDIR)" ; \ + idir="$(DESTDIR)$(HACKDIR)" ; \ if [ @SETUID_AUTH@ = yes ]; then \ inst="$(INSTALL_SETUID)" ; \ else \ @@ -366,25 +366,25 @@ install-program:: $(SETUID_EXES) # Symlink from xscreensaver-demo -> xscreensaver-settings in /usr/bin/ install-program:: - @D=$(install_prefix)$(bindir) ; \ + @D=$(DESTDIR)$(bindir) ; \ echo ln -sf xscreensaver-settings $$D/xscreensaver-demo ; \ ln -sf xscreensaver-settings $$D/xscreensaver-demo install-ad: XScreenSaver.ad - @if [ ! -d $(install_prefix)$(AD_DIR) ]; then \ - $(INSTALL_DIRS) $(install_prefix)$(AD_DIR) ; \ + @if [ ! -d $(DESTDIR)$(AD_DIR) ]; then \ + $(INSTALL_DIRS) $(DESTDIR)$(AD_DIR) ; \ fi ; \ echo $(INSTALL_DATA) XScreenSaver.ad \ - $(install_prefix)$(AD_DIR)/XScreenSaver ; \ + $(DESTDIR)$(AD_DIR)/XScreenSaver ; \ if $(INSTALL_DATA) XScreenSaver.ad \ - $(install_prefix)$(AD_DIR)/XScreenSaver ; then \ + $(DESTDIR)$(AD_DIR)/XScreenSaver ; then \ true ; \ else \ e=echo ; \ - if [ -f $(install_prefix)$(AD_DIR)/XScreenSaver ]; then \ + if [ -f $(DESTDIR)$(AD_DIR)/XScreenSaver ]; then \ $$e "" ;\ $$e " ####################################################################";\ - $$e " Warning: unable to install $(install_prefix)$(AD_DIR)/XScreenSaver" ;\ + $$e " Warning: unable to install $(DESTDIR)$(AD_DIR)/XScreenSaver" ;\ $$e " That file exists, and is unwritable. It is probably from" ;\ $$e " an older version of xscreensaver, and could cause things" ;\ $$e " to malfunction. Please delete it!" ;\ @@ -394,7 +394,7 @@ install-ad: XScreenSaver.ad else \ $$e "" ;\ $$e " ####################################################################";\ - $$e " Warning: unable to install $(install_prefix)$(AD_DIR)/XScreenSaver" ;\ + $$e " Warning: unable to install $(DESTDIR)$(AD_DIR)/XScreenSaver" ;\ $$e " This is probably ok; it should work without that file." ;\ $$e " ####################################################################";\ $$e "" ;\ @@ -420,7 +420,7 @@ install-man:: $(MENA) $(MENB) \ INST() { \ TH=".TH XScreenSaver $$SUF \"$$V\" \"X Version 11\"" ; \ - DIR="$(install_prefix)$(mandir)/man$$SUF" ; \ + DIR="$(DESTDIR)$(mandir)/man$$SUF" ; \ if [ ! -d $$DIR ]; then \ echo $(INSTALL_DIRS) $$DIR ; \ $(INSTALL_DIRS) $$DIR ; \ @@ -441,7 +441,7 @@ install-man:: $(MENA) $(MENB) # Symlink from xscreensaver-demo.1 -> xscreensaver-settings.1 in /usr/man/man1/ install-man:: - @D=$(install_prefix)$(mandir)/man$(mansuffixA) ; \ + @D=$(DESTDIR)$(mandir)/man$(mansuffixA) ; \ F1=xscreensaver-settings.$(mansuffixA) ; \ F2=xscreensaver-demo.$(mansuffixA) ; \ echo ln -sf $$F1 $$D/$$F2 ; \ @@ -457,32 +457,32 @@ OLD_MEN = xscreensaver-getimage.man xscreensaver-getimage-file.man \ xscreensaver-demo.man uninstall-program:: @for program in $(EXES) $(OLD_EXES); do \ - echo rm -f $(install_prefix)$(bindir)/$$program ; \ - rm -f $(install_prefix)$(bindir)/$$program ; \ + echo rm -f $(DESTDIR)$(bindir)/$$program ; \ + rm -f $(DESTDIR)$(bindir)/$$program ; \ done uninstall-program:: @for program in $(UTIL_EXES) $(SETUID_EXES); do \ - echo rm -f $(install_prefix)$(HACKDIR)/$$program ; \ - rm -f $(install_prefix)$(HACKDIR)/$$program ; \ + echo rm -f $(DESTDIR)$(HACKDIR)/$$program ; \ + rm -f $(DESTDIR)$(HACKDIR)/$$program ; \ done uninstall-ad: - rm -f $(install_prefix)$(AD_DIR)/XScreenSaver + rm -f $(DESTDIR)$(AD_DIR)/XScreenSaver uninstall-man: @men="$(MEN) $(OLD_MEN)" ; \ for man in $$men; do \ instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ; \ - echo rm -f $(install_prefix)$(manAdir)/$$instname* ; \ - rm -f $(install_prefix)$(manAdir)/$$instname* ; \ + echo rm -f $(DESTDIR)$(manAdir)/$$instname* ; \ + rm -f $(DESTDIR)$(manAdir)/$$instname* ; \ done install-pam: xscreensaver.pam @src="xscreensaver.pam" ; \ name=`sed -n 's/.*PAM_SERVICE_NAME[ ]*"\([^"]*\)".*$$/\1/p' \ < ../config.h` ; \ - dir="$(install_prefix)$(PAM_DIR)" ; \ + dir="$(DESTDIR)$(PAM_DIR)" ; \ conf="$(PAM_CONF)" ; \ \ if [ -z "$$name" ]; then \ @@ -490,9 +490,9 @@ install-pam: xscreensaver.pam exit 0 ; \ fi ; \ \ - if [ ! -d $(install_prefix)$(PAM_ROOT) ]; then \ - echo $(INSTALL_DIRS) $(install_prefix)$(PAM_ROOT) ; \ - $(INSTALL_DIRS) $(install_prefix)$(PAM_ROOT) ; \ + if [ ! -d $(DESTDIR)$(PAM_ROOT) ]; then \ + echo $(INSTALL_DIRS) $(DESTDIR)$(PAM_ROOT) ; \ + $(INSTALL_DIRS) $(DESTDIR)$(PAM_ROOT) ; \ fi ; \ \ if [ -d $$dir ] ; then \ @@ -575,20 +575,20 @@ install-pam: xscreensaver.pam # into /usr/share/applications/ install-gnome:: xscreensaver.desktop xscreensaver-settings.desktop @if [ "$(GTK_DATADIR)" != "" ]; then \ - if [ ! -d "$(install_prefix)$(GTK_APPDIR)" ]; then \ - echo $(INSTALL_DIRS) "$(install_prefix)$(GTK_APPDIR)" ;\ - $(INSTALL_DIRS) "$(install_prefix)$(GTK_APPDIR)" ;\ + if [ ! -d "$(DESTDIR)$(GTK_APPDIR)" ]; then \ + echo $(INSTALL_DIRS) "$(DESTDIR)$(GTK_APPDIR)" ;\ + $(INSTALL_DIRS) "$(DESTDIR)$(GTK_APPDIR)" ;\ fi ;\ old=xscreensaver-properties.desktop ;\ - if [ -f "$(install_prefix)$(GTK_APPDIR)/$$old" ]; then \ - echo rm -f "$(install_prefix)$(GTK_APPDIR)/$$old" ;\ - rm -f "$(install_prefix)$(GTK_APPDIR)/$$old" ;\ + if [ -f "$(DESTDIR)$(GTK_APPDIR)/$$old" ]; then \ + echo rm -f "$(DESTDIR)$(GTK_APPDIR)/$$old" ;\ + rm -f "$(DESTDIR)$(GTK_APPDIR)/$$old" ;\ fi ;\ for name in xscreensaver.desktop xscreensaver-settings.desktop ; do\ - echo $(INSTALL_DATA) $$name $(install_prefix)$(GTK_APPDIR)/$$name;\ - $(INSTALL_DATA) $$name $(install_prefix)$(GTK_APPDIR)/$$name;\ - echo chmod a+x $(install_prefix)$(GTK_APPDIR)/$$name ;\ - chmod a+x $(install_prefix)$(GTK_APPDIR)/$$name ;\ + echo $(INSTALL_DATA) $$name $(DESTDIR)$(GTK_APPDIR)/$$name ;\ + $(INSTALL_DATA) $$name $(DESTDIR)$(GTK_APPDIR)/$$name ;\ + echo chmod a+x $(DESTDIR)$(GTK_APPDIR)/$$name ;\ + chmod a+x $(DESTDIR)$(GTK_APPDIR)/$$name ;\ done ;\ fi @@ -599,27 +599,27 @@ install-gnome:: xscreensaver.desktop xscreensaver-settings.desktop # Or would that make it be enabled by default? # install-gnome:: xscreensaver.service - @if [ ! -d "$(install_prefix)$(GTK_SHAREDIR)" ]; then \ - echo $(INSTALL_DIRS) "$(install_prefix)$(GTK_SHAREDIR)" ;\ - $(INSTALL_DIRS) "$(install_prefix)$(GTK_SHAREDIR)" ;\ + @if [ ! -d "$(DESTDIR)$(GTK_SHAREDIR)" ]; then \ + echo $(INSTALL_DIRS) "$(DESTDIR)$(GTK_SHAREDIR)" ;\ + $(INSTALL_DIRS) "$(DESTDIR)$(GTK_SHAREDIR)" ;\ fi ;\ name=xscreensaver.service ;\ - echo $(INSTALL_DATA) $$name $(install_prefix)$(GTK_SHAREDIR)/$$name ;\ - $(INSTALL_DATA) $$name $(install_prefix)$(GTK_SHAREDIR)/$$name + echo $(INSTALL_DATA) $$name $(DESTDIR)$(GTK_SHAREDIR)/$$name ;\ + $(INSTALL_DATA) $$name $(DESTDIR)$(GTK_SHAREDIR)/$$name # xscreensaver.png # into /usr/share/pixmaps/ install-gnome:: $(LOGO) @if [ "$(GTK_DATADIR)" != "" ]; then \ - if [ ! -d "$(install_prefix)$(GTK_ICONDIR)" ]; then \ - echo $(INSTALL_DIRS) "$(install_prefix)$(GTK_ICONDIR)" ;\ - $(INSTALL_DIRS) "$(install_prefix)$(GTK_ICONDIR)" ;\ + if [ ! -d "$(DESTDIR)$(GTK_ICONDIR)" ]; then \ + echo $(INSTALL_DIRS) "$(DESTDIR)$(GTK_ICONDIR)" ;\ + $(INSTALL_DIRS) "$(DESTDIR)$(GTK_ICONDIR)" ;\ fi ;\ target=xscreensaver.png ;\ echo $(INSTALL_DATA) $(LOGO) \ - $(install_prefix)$(GTK_ICONDIR)/$$target ;\ + $(DESTDIR)$(GTK_ICONDIR)/$$target ;\ $(INSTALL_DATA) $(LOGO) \ - $(install_prefix)$(GTK_ICONDIR)/$$target ;\ + $(DESTDIR)$(GTK_ICONDIR)/$$target ;\ fi install-gnome:: uninstall-old-gnome-icons @@ -645,12 +645,12 @@ uninstall-gnome:: @if [ "$(GTK_DATADIR)" != "" ]; then \ old=xscreensaver-properties.desktop ;\ if [ -f "$old" ]; then \ - echo rm -f $(install_prefix)$(GTK_APPDIR)/$$old ;\ - rm -f $(install_prefix)$(GTK_APPDIR)/$$old ;\ + echo rm -f $(DESTDIR)$(GTK_APPDIR)/$$old ;\ + rm -f $(DESTDIR)$(GTK_APPDIR)/$$old ;\ fi ;\ for f in xscreensaver.desktop xscreensaver-settings.desktop; do \ - echo rm -f $(install_prefix)$(GTK_APPDIR)/$$f ;\ - rm -f $(install_prefix)$(GTK_APPDIR)/$$f ;\ + echo rm -f $(DESTDIR)$(GTK_APPDIR)/$$f ;\ + rm -f $(DESTDIR)$(GTK_APPDIR)/$$f ;\ done ;\ fi @@ -659,15 +659,15 @@ uninstall-gnome:: uninstall-gnome:: @if [ "$(GTK_ICONDIR)" != "" ]; then \ target=xscreensaver.xpm ;\ - echo rm -f $(install_prefix)$(GTK_ICONDIR)/$$target ;\ - rm -f $(install_prefix)$(GTK_ICONDIR)/$$target ;\ + echo rm -f $(DESTDIR)$(GTK_ICONDIR)/$$target ;\ + rm -f $(DESTDIR)$(GTK_ICONDIR)/$$target ;\ fi # /usr/share/xscreensaver/ui/*.png and *.ui no longer used as of 2022, 6.05. uninstall-gnome:: @if [ "$(GTK_ICONDIR)" != "" ]; then \ - echo rm -rf $(install_prefix)$(GTK_SHAREDIR)/ui ;\ - rm -rf $(install_prefix)$(GTK_SHAREDIR)/ui ;\ + echo rm -rf $(DESTDIR)$(GTK_SHAREDIR)/ui ;\ + rm -rf $(DESTDIR)$(GTK_SHAREDIR)/ui ;\ fi # What is all this crap with the wrong logo? @@ -676,10 +676,10 @@ uninstall-gnome:: uninstall-gnome:: uninstall-old-gnome-icons uninstall-old-gnome-icons:: @for f in \ - "$(install_prefix)$(GTK_DATADIR)/icons"/*/*/apps/xscreensaver.png \ - "$(install_prefix)$(GTK_DATADIR)/icons"/*/*/apps/xscreensaver.svg \ - "$(install_prefix)$(GTK_ICONDIR)/xscreensaver.xpm" \ - "$(install_prefix)$(GTK_ICONDIR)/xscreensaver.svg" ;\ + "$(DESTDIR)$(GTK_DATADIR)/icons"/*/*/apps/xscreensaver.png \ + "$(DESTDIR)$(GTK_DATADIR)/icons"/*/*/apps/xscreensaver.svg \ + "$(DESTDIR)$(GTK_ICONDIR)/xscreensaver.xpm" \ + "$(DESTDIR)$(GTK_ICONDIR)/xscreensaver.svg" ;\ do \ if [ -f "$$f" ]; then \ echo rm -f "$$f" ;\ @@ -694,7 +694,7 @@ uninstall-gnome:: # /usr/share/xscreensaver/config/README install-xml: - @dest=$(install_prefix)$(HACK_CONF_DIR) ; \ + @dest=$(DESTDIR)$(HACK_CONF_DIR) ; \ if [ ! -d $$dest ]; then \ $(INSTALL_DIRS) $$dest ; \ fi ; \ @@ -705,7 +705,7 @@ install-xml: # /usr/share/xscreensaver/config/README uninstall-xml: - rm -f $(install_prefix)$(HACK_CONF_DIR)/README + rm -f $(DESTDIR)$(HACK_CONF_DIR)/README ############################################################################## diff --git a/hacks/Makefile.in b/hacks/Makefile.in index 38aebd07a..89a9861de 100644 --- a/hacks/Makefile.in +++ b/hacks/Makefile.in @@ -10,7 +10,7 @@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = .. -install_prefix = +DESTDIR = prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ @@ -286,19 +286,19 @@ install-strip: # the hacks, in $HACKDIR install-program:: $(EXES) - @if [ ! -d $(install_prefix)$(HACKDIR) ]; then \ - $(INSTALL_DIRS) $(install_prefix)$(HACKDIR) ; \ + @if [ ! -d $(DESTDIR)$(HACKDIR) ]; then \ + $(INSTALL_DIRS) $(DESTDIR)$(HACKDIR) ; \ fi ; \ for program in $(EXES); do \ echo $(INSTALL_PROGRAM) $$program \ - $(install_prefix)$(HACKDIR)/$$program ; \ + $(DESTDIR)$(HACKDIR)/$$program ; \ $(INSTALL_PROGRAM) $$program \ - $(install_prefix)$(HACKDIR)/$$program ; \ + $(DESTDIR)$(HACKDIR)/$$program ; \ done install-scripts: $(SCRIPTS) munge-scripts - @if [ ! -d $(install_prefix)$(HACKDIR) ]; then \ - $(INSTALL_DIRS) $(install_prefix)$(HACKDIR) ; \ + @if [ ! -d $(DESTDIR)$(HACKDIR) ]; then \ + $(INSTALL_DIRS) $(DESTDIR)$(HACKDIR) ; \ fi ; \ for program in $(SCRIPTS); do \ if [ -r $$program ] ; then \ @@ -307,9 +307,9 @@ install-scripts: $(SCRIPTS) munge-scripts p=$(srcdir)/$$program ; \ fi ; \ echo $(INSTALL_SCRIPT) $$p \ - $(install_prefix)$(HACKDIR)/$$program ; \ + $(DESTDIR)$(HACKDIR)/$$program ; \ $(INSTALL_SCRIPT) $$p \ - $(install_prefix)$(HACKDIR)/$$program ; \ + $(DESTDIR)$(HACKDIR)/$$program ; \ done munge-scripts: $(SCRIPTS) @@ -342,8 +342,8 @@ install-man: $(MEN) TH=".TH XScreenSaver $(mansuffix) \"$$V\" \"X Version 11\"" ; \ echo "installing man pages: $$TH" ; \ \ - if [ ! -d $(install_prefix)$(manNdir) ]; then \ - $(INSTALL_DIRS) $(install_prefix)$(manNdir) ; \ + if [ ! -d $(DESTDIR)$(manNdir) ]; then \ + $(INSTALL_DIRS) $(DESTDIR)$(manNdir) ; \ fi ; \ \ for man in $$men; do \ @@ -354,14 +354,14 @@ install-man: $(MEN) -e 's@(MANSUFFIX)@($(mansuffix))@g' \ < $(srcdir)/$$man > $$T ; \ echo $(INSTALL_DATA) $(srcdir)/$$man \ - $(install_prefix)$(manNdir)/$$instname ; \ + $(DESTDIR)$(manNdir)/$$instname ; \ $(INSTALL_DATA) $$T \ - $(install_prefix)$(manNdir)/$$instname ; \ + $(DESTDIR)$(manNdir)/$$instname ; \ done ; \ rm -f $$T install-xml: - @dest=$(install_prefix)$(HACK_CONF_DIR) ; \ + @dest=$(DESTDIR)$(HACK_CONF_DIR) ; \ if [ ! -d $$dest ]; then \ $(INSTALL_DIRS) $$dest ; \ fi ; \ @@ -375,20 +375,20 @@ install-xml: uninstall-program: @for program in $(EXES) $(RETIRED_EXES) $(SCRIPTS); do \ - echo rm -f $(install_prefix)$(HACKDIR)/$$program ; \ - rm -f $(install_prefix)$(HACKDIR)/$$program ; \ + echo rm -f $(DESTDIR)$(HACKDIR)/$$program ; \ + rm -f $(DESTDIR)$(HACKDIR)/$$program ; \ done uninstall-man: @men="$(MEN) $(RETIRED_MEN)" ; \ for man in $$men; do \ instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ; \ - echo rm -f $(install_prefix)$(manNdir)/$$instname* ; \ - rm -f $(install_prefix)$(manNdir)/$$instname* ; \ + echo rm -f $(DESTDIR)$(manNdir)/$$instname* ; \ + rm -f $(DESTDIR)$(manNdir)/$$instname* ; \ done uninstall-xml: - @dest=$(install_prefix)$(HACK_CONF_DIR) ; \ + @dest=$(DESTDIR)$(HACK_CONF_DIR) ; \ for file in $(EXES) $(RETIRED_EXES) $(SCRIPTS) ; do \ echo rm -f $$dest/$$file.xml ; \ rm -f $$dest/$$file.xml ; \ diff --git a/hacks/fonts/Makefile.in b/hacks/fonts/Makefile.in index 7e272c856..4afc13e32 100644 --- a/hacks/fonts/Makefile.in +++ b/hacks/fonts/Makefile.in @@ -1,4 +1,4 @@ -# hacks/fonts/Makefile.in --- xscreensaver, Copyright © 2021-2023 Jamie Zawinski. +# hacks/fonts/Makefile.in --- xscreensaver, Copyright © 2021-2025 Jamie Zawinski. # the `../configure' script generates `hacks/fonts/Makefile' from this file. @SET_MAKE@ @@ -7,7 +7,7 @@ VPATH = ${srcdir} top_srcdir = @top_srcdir@ top_builddir = .. -install_prefix = +DESTDIR = prefix = @prefix@ datarootdir = @datarootdir@ datadir = @datadir@ @@ -66,7 +66,7 @@ install-fonts: @if [ -z "$(FONT_DIR)" ]; then \ echo "not installing fonts" ; \ else \ - dest="$(install_prefix)$(FONT_DIR)" ; \ + dest="$(DESTDIR)$(FONT_DIR)" ; \ if [ ! -d "$$dest" ]; then \ echo $(INSTALL_DIRS) "$$dest" ; \ $(INSTALL_DIRS) "$$dest" ; \ @@ -80,12 +80,12 @@ install-fonts: uninstall:: uninstall-fonts uninstall-fonts: @if ! [ -z "$(FONT_DIR)" ]; then \ - dest="$(install_prefix)$(FONT_DIR)" ; \ + dest="$(DESTDIR)$(FONT_DIR)" ; \ for f in $(FONTS) ; do \ echo $(RM) $$dest/$$f ; \ $(RM) $$dest/$$f ; \ done ; \ - rmdir "$(install_prefix)$(FONT_DIR)" ; \ + rmdir "$(DESTDIR)$(FONT_DIR)" ; \ exit 0 ; \ fi diff --git a/hacks/glx/Makefile.in b/hacks/glx/Makefile.in index d6b7dc939..5e6dfa778 100644 --- a/hacks/glx/Makefile.in +++ b/hacks/glx/Makefile.in @@ -10,7 +10,7 @@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = .. -install_prefix = +DESTDIR = prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ @@ -339,7 +339,7 @@ install-strip: # the hacks, in $HACKDIR install-program:: $(EXES) @exes="$(HACK_EXES_1) @GL_UTIL_EXES@" ; \ - idir="$(install_prefix)$(HACKDIR)" ; \ + idir="$(DESTDIR)$(HACKDIR)" ; \ if ( echo $$exes | grep -q . ); then \ if [ ! -d $$idir ]; then \ $(INSTALL_DIRS) $$idir ; \ @@ -393,8 +393,8 @@ install-program:: $(EXES) install-scripts: $(SCRIPTS) munge-scripts @ \ if ! ( echo $(HACK_EXES_1) | grep -q . ); then exit 0 ; fi ; \ - if [ ! -d $(install_prefix)$(HACKDIR) ]; then \ - $(INSTALL_DIRS) $(install_prefix)$(HACKDIR) ; \ + if [ ! -d $(DESTDIR)$(HACKDIR) ]; then \ + $(INSTALL_DIRS) $(DESTDIR)$(HACKDIR) ; \ fi ; \ for program in $(SCRIPTS); do \ if [ -r $$program ] ; then \ @@ -403,9 +403,9 @@ install-scripts: $(SCRIPTS) munge-scripts p=$(srcdir)/$$program ; \ fi ; \ echo $(INSTALL_SCRIPT) $$p \ - $(install_prefix)$(HACKDIR)/$$program ; \ + $(DESTDIR)$(HACKDIR)/$$program ; \ $(INSTALL_SCRIPT) $$p \ - $(install_prefix)$(HACKDIR)/$$program ; \ + $(DESTDIR)$(HACKDIR)/$$program ; \ done munge-scripts: $(SCRIPTS) @@ -439,8 +439,8 @@ install-man: $(MEN) if ! ( echo $(HACK_EXES_1) | grep -q . ); then exit 0 ; fi ; \ echo "installing man pages: $$TH" ; \ \ - if [ ! -d $(install_prefix)$(manNdir) ]; then \ - $(INSTALL_DIRS) $(install_prefix)$(manNdir) ; \ + if [ ! -d $(DESTDIR)$(manNdir) ]; then \ + $(INSTALL_DIRS) $(DESTDIR)$(manNdir) ; \ fi ; \ \ for man in $$men; do \ @@ -451,14 +451,14 @@ install-man: $(MEN) -e 's@(MANSUFFIX)@($(mansuffix))@g' \ < $(srcdir)/$$man > $$T ; \ echo $(INSTALL_DATA) $(srcdir)/$$man \ - $(install_prefix)$(manNdir)/$$instname ; \ + $(DESTDIR)$(manNdir)/$$instname ; \ $(INSTALL_DATA) $$T \ - $(install_prefix)$(manNdir)/$$instname ; \ + $(DESTDIR)$(manNdir)/$$instname ; \ done ; \ rm -f $$T install-xml: - @dest=$(install_prefix)$(HACK_CONF_DIR) ; \ + @dest=$(DESTDIR)$(HACK_CONF_DIR) ; \ if [ ! -d $$dest ]; then \ $(INSTALL_DIRS) $$dest ; \ fi ; \ @@ -473,7 +473,7 @@ install-xml: # the hacks, in $HACKDIR uninstall-program:: @exes="$(HACK_EXES) $(RETIRED_EXES) $(SCRIPTS) @GL_UTIL_EXES@" ;\ - idir="$(install_prefix)$(HACKDIR)" ; \ + idir="$(DESTDIR)$(HACKDIR)" ; \ for program in $$exes; do \ echo rm -f $$idir/$$program ; \ rm -f $$idir/$$program ; \ @@ -481,18 +481,18 @@ uninstall-program:: # $HACKDIR/xscreensaver-gl-visual used to be $bindir/xscreensaver-gl-helper uninstall-program:: - rm -f $(install_prefix)$(bindir)/xscreensaver-gl-helper + rm -f $(DESTDIR)$(bindir)/xscreensaver-gl-helper uninstall-man: @men="$(MEN) $(RETIRED_MEN)" ; \ for man in $$men; do \ instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ; \ - echo rm -f $(install_prefix)$(manNdir)/$$instname* ; \ - rm -f $(install_prefix)$(manNdir)/$$instname* ; \ + echo rm -f $(DESTDIR)$(manNdir)/$$instname* ; \ + rm -f $(DESTDIR)$(manNdir)/$$instname* ; \ done uninstall-xml: - @dest=$(install_prefix)$(HACK_CONF_DIR) ; \ + @dest=$(DESTDIR)$(HACK_CONF_DIR) ; \ for file in $(EXES) $(RETIRED_EXES) $(SCRIPTS) ; do \ echo rm -f $$dest/$$file.xml ; \ rm -f $$dest/$$file.xml ; \ diff --git a/po/Makefile.in.in b/po/Makefile.in.in index 03e816f6d..123a28a36 100644 --- a/po/Makefile.in.in +++ b/po/Makefile.in.in @@ -61,8 +61,6 @@ # The install-data-yes rule made no provision for this, and would # just error out when the .gmo files were not there. # -# - $(DESTDIR) was being used where $(install_prefix) should have been. -# # - For xscreensaver, $(prefix) is generally /usr/X11R6/, but some files # need to go under /usr/ instead of under /usr/X11R6/ -- for those, we # use @PO_DATADIR@ instead of @prefix@. So I changed $(datadir) and @@ -111,7 +109,7 @@ localedir = $(datadir)/locale gnulocaledir = $(localedir) #gettextsrcdir = $(prefix)/share/glib-2.0/gettext/po subdir = po -DESTDIR = $(install_prefix) +DESTDIR = INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -225,7 +223,7 @@ install-data-yes: all *) destdir=$(localedir);; \ esac; \ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ - dir=$(install_prefix)$$destdir/$$lang/LC_MESSAGES; \ + dir=$(DESTDIR)$$destdir/$$lang/LC_MESSAGES; \ dest=$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ if test -r $$cat -o -r $$cat.m; then \ echo $(MKINSTALLDIRS) $$dir; \ @@ -256,10 +254,10 @@ uninstall: cat=`basename $$cat`; \ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ suffix="$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \ - for f in $(install_prefix)$(localedir)/$$suffix \ - $(install_prefix)$(localedir)/$$suffix.m \ - $(install_prefix)$(gnulocaledir)/$$suffix \ - $(install_prefix)$(gnulocaledir)/$$suffix.m; do \ + for f in $(DESTDIR)$(localedir)/$$suffix \ + $(DESTDIR)$(localedir)/$$suffix.m \ + $(DESTDIR)$(gnulocaledir)/$$suffix \ + $(DESTDIR)$(gnulocaledir)/$$suffix.m; do \ if [ -f $$f ]; then \ echo rm -f $$f; \ rm -f $$f; \ From 161c9d2594b68d12e084902fbfa4072e41ae04aa Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:17:13 +0200 Subject: [PATCH 02/25] make: delete old PREFERRED_DEMO in all cases Although, this should just be done by pulling the rm out of the conditional --- driver/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/driver/Makefile.in b/driver/Makefile.in index edae8cf01..51db423b5 100644 --- a/driver/Makefile.in +++ b/driver/Makefile.in @@ -956,6 +956,7 @@ xscreensaver-settings: @PREFERRED_DEMO_PROGRAM@ "therefore no xscreensaver-settings!" ; \ rm -f $@@EXEEXT@ ; \ else \ + rm -f $@@EXEEXT@ ; \ echo cp -p @PREFERRED_DEMO_PROGRAM@@EXEEXT@ $@@EXEEXT@ ; \ cp -p @PREFERRED_DEMO_PROGRAM@@EXEEXT@ $@@EXEEXT@ ; \ fi From 5cc081217a9ed5f9b2235ba19c615046e0a1d9f6 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 17:03:00 +0200 Subject: [PATCH 03/25] make: warn/error on deprecated/disliked configs Error: --with-gles --with-glx breaks GLSL Warn: --without-setuid-hacks breaks hacks/sonar (jwz: for no good reason) --- configure | 21 +++++++++++++++++++++ configure.ac | 25 +++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 894999ee2..cf06a858e 100755 --- a/configure +++ b/configure @@ -1575,7 +1575,9 @@ User Interface Options: Graphics Options: --with-gles Emulate OpenGL 1.3 in terms of OpenGL ES 1.x. + Do not do this: it doesn't mean what you think. --with-glx Use GLX to interface OpenGL and X11 instead of EGL. + Do not do this: it will make GLSL fail. --with-gle Include support for the GL Extrusion library. --with-jpeg Include support for the JPEG library. --with-png Include support for the PNG library. @@ -22964,6 +22966,7 @@ CONF_STATUS=0 warn_prefix_1=" Warning:" warn_prefix_2=" Note:" +warn_prefix_3=" Error:" warn_prefix="$warn_prefix_1" warning=no @@ -23410,6 +23413,19 @@ if test "$ac_macosx" = yes -a "$enable_locking" = yes ; then warn2 "THIS DOES NOT WORK! Don't do this!" fi +# Fucking Gentoo... +if test "$have_jwzgles" = yes ; then + warn_prefix="$warn_prefix_3" + warn "The --with-gles option does not do what you think. Do not use it." + exit 1 +fi + +if test "$have_egl" = no; then + warn_prefix="$warn_prefix_3" + warn "Using --with-glx means GLSL won't work. Don't do it!" + exit 1 +fi + if test "$have_jwzgles" = yes ; then warn "Do not use --with-gles unless you are sure that you know" warn2 "what you are doing! It is not recommended on normal X11" @@ -23421,6 +23437,11 @@ if test "$have_jwzgles" = yes ; then fi fi +if test "$setuid_hacks" = no; then + warn "Using --without-setuid-hacks breaks 'sonar' for no good reason." + warn2 "Don't do it." +fi + # You are in a twisty maze of namespaces and syntaxes, all alike. # Expand all of these as the Makefile will probably expand them. # Fuck the skull of Unix. diff --git a/configure.ac b/configure.ac index 423ea450d..4f3231a1a 100644 --- a/configure.ac +++ b/configure.ac @@ -3392,7 +3392,8 @@ AC_ARG_WITH(gl, [ Graphics Options: - --with-gles Emulate OpenGL 1.3 in terms of OpenGL ES 1.x.], + --with-gles Emulate OpenGL 1.3 in terms of OpenGL ES 1.x. + Do not do this: it doesn't mean what you think.], [with_gl="$withval"; with_gl_req="$withval"],[with_gl=yes]) HANDLE_X_PATH_ARG(with_gl, --with-gl, GL) @@ -3573,7 +3574,8 @@ have_glx=no have_egl=no with_egl_req=unspecified AC_ARG_WITH(glx, -[ --with-glx Use GLX to interface OpenGL and X11 instead of EGL.], +[ --with-glx Use GLX to interface OpenGL and X11 instead of EGL. + Do not do this: it will make GLSL fail.], [with_egl="$withval"; with_egl_req="$withval"], [with_glx=no]) @@ -4618,6 +4620,7 @@ CONF_STATUS=0 warn_prefix_1=" Warning:" warn_prefix_2=" Note:" +warn_prefix_3=" Error:" warn_prefix="$warn_prefix_1" warning=no @@ -5075,6 +5078,19 @@ if test "$ac_macosx" = yes -a "$enable_locking" = yes ; then warn2 "THIS DOES NOT WORK! Don't do this!" fi +# Fucking Gentoo... +if test "$have_jwzgles" = yes ; then + warn_prefix="$warn_prefix_3" + warn "The --with-gles option does not do what you think. Do not use it." + exit 1 +fi + +if test "$have_egl" = no; then + warn_prefix="$warn_prefix_3" + warn "Using --with-glx means GLSL won't work. Don't do it!" + exit 1 +fi + if test "$have_jwzgles" = yes ; then warn "Do not use --with-gles unless you are sure that you know" warn2 "what you are doing! It is not recommended on normal X11" @@ -5086,6 +5102,11 @@ if test "$have_jwzgles" = yes ; then fi fi +if test "$setuid_hacks" = no; then + warn "Using --without-setuid-hacks breaks 'sonar' for no good reason." + warn2 "Don't do it." +fi + # You are in a twisty maze of namespaces and syntaxes, all alike. # Expand all of these as the Makefile will probably expand them. From 790d7b23f20c8592277633ec0628c5bf3f567013 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 17:17:10 +0200 Subject: [PATCH 04/25] make: Fix PAM patching logic Pick up patches from build system's PAM_DIR, instead of package chroot's PAM_DIR (which will generally be empty) Of course, advisedness of such build system dependence is left as an exercise to the reader --- driver/Makefile.in | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/driver/Makefile.in b/driver/Makefile.in index 51db423b5..b5680ec47 100644 --- a/driver/Makefile.in +++ b/driver/Makefile.in @@ -495,12 +495,12 @@ install-pam: xscreensaver.pam $(INSTALL_DIRS) $(DESTDIR)$(PAM_ROOT) ; \ fi ; \ \ - if [ -d $$dir ] ; then \ + if [ -d $(PAM_DIR) ] ; then \ \ - if [ -f $$dir/xdm ]; then \ - src2=$$dir/xdm ; \ - elif [ -f $$dir/login ]; then \ - src2=$$dir/login ; \ + if [ -f $(PAM_DIR)/xdm ]; then \ + src2=$(PAM_DIR)/xdm ; \ + elif [ -f $(PAM_DIR)/login ]; then \ + src2=$(PAM_DIR)/login ; \ fi ; \ \ if [ -z "$$src2" ]; then \ From bc2839ee358c6691ff2bcadab3909b501742438c Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:20:46 +0200 Subject: [PATCH 05/25] app-defaults: use xdg commands (more generic) --- driver/XScreenSaver.ad.in | 6 ++++-- driver/XScreenSaver_ad.h | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/driver/XScreenSaver.ad.in b/driver/XScreenSaver.ad.in index 6abaef220..abc4d8c4b 100644 --- a/driver/XScreenSaver.ad.in +++ b/driver/XScreenSaver.ad.in @@ -98,8 +98,10 @@ ! non-Gnome systems: ! @NOGNOME@*loadURL: x-www-browser '%s' || firefox '%s' || chromium-browser '%s' -@NOGNOME@*manualCommand: lxterminal -T '%s manual' \ -@NOGNOME@ -e /bin/sh -c 'man "%s" ; read foo' +!@NOGNOME@*manualCommand: lxterminal -T '%s manual' \ +!@NOGNOME@ -e /bin/sh -c 'man "%s" ; read foo' +@NOGNOME@*manualCommand: xdg-open man:%s || \ +@NOGNOME@ x-terminal-emulator -e /bin/sh -c 'man "%s"' ! The strftime(3) format string for printing the time on the password dialog. diff --git a/driver/XScreenSaver_ad.h b/driver/XScreenSaver_ad.h index 420a474a4..df1c16987 100644 --- a/driver/XScreenSaver_ad.h +++ b/driver/XScreenSaver_ad.h @@ -37,8 +37,8 @@ "*demoCommand: xscreensaver-settings", "*helpURL: https://www.jwz.org/xscreensaver/man.html", "*loadURL: x-www-browser '%s' || firefox '%s' || chromium-browser '%s'", -"*manualCommand: lxterminal -T '%s manual' \ - -e /bin/sh -c 'man \"%s\" ; read foo'", +"*manualCommand: xdg-open man:%s || \ + x-terminal-emulator -e /bin/sh -c 'man \"%s\"'", "*dateFormat: %I:%M %p, %a %b %e", "*newLoginCommand: no-such-login-manager", "XScreenSaver.pointerHysteresis: 10", From 4346754aec3ed181fcf3596e266fe37927ff2180 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 16:58:06 +0200 Subject: [PATCH 06/25] Add unitary debian package jwz dislikes debian fragmenting the package --- Makefile.in | 85 +++++++++++++++++++++++++++++++++++--------- README | 2 ++ configure | 53 +++++++++++++++++++++++++++ configure.ac | 7 +++- debian/README | 17 +++++++++ debian/changelog | 5 +++ debian/control | 57 +++++++++++++++++++++++++++++ debian/copyright | 15 ++++++++ debian/docs | 2 ++ debian/postinst | 9 +++++ debian/prerm | 9 +++++ debian/rules | 19 ++++++++++ debian/source/format | 1 + debian/watch | 2 ++ 14 files changed, 265 insertions(+), 18 deletions(-) create mode 100644 debian/README create mode 100644 debian/changelog create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/docs create mode 100755 debian/postinst create mode 100755 debian/prerm create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 debian/watch diff --git a/Makefile.in b/Makefile.in index df7843b08..2df2ee169 100644 --- a/Makefile.in +++ b/Makefile.in @@ -14,10 +14,22 @@ TARFILES = README README.hacking INSTALL \ install-sh config.guess config.rpath aclocal.m4 \ ax_pthread.m4 config.sub \ intltool-merge.in intltool-extract.in intltool-update.in \ - xscreensaver.spec + xscreensaver.spec $(DEBFILES) -TAR = gnutar -TAR_ARGS = --owner=0 --group=0 --posix --no-acls --no-xattrs --no-selinux +DEBFILES = debian/changelog \ + debian/control \ + debian/copyright \ + debian/docs \ + debian/postinst \ + debian/prerm \ + debian/README \ + debian/rules \ + debian/source/format \ + debian/watch + +TAR = @TAR@ +TAR_ARGS = -v --owner=0 --group=0 --posix --no-acls --no-xattrs --no-selinux +TAR_DIR = archive # Using $(MAKE) directly means the shell executes things even with "make -n" @@ -83,7 +95,8 @@ _tar: NAME="xscreensaver-$$VERS" ; \ rm -rf $$NAME ; ln -s . $$NAME ; \ LIST="tar$$$$.txt" ; \ - ADIR=archive/ ; \ + ADIR="$(TAR_DIR)" ; \ + [ -d "$$ADIR" ] || mkdir "$$ADIR" ; \ rm -f "$$LIST" ; \ for subdir in . $(SUBDIRS2) ; do \ ( cd $$subdir ; \ @@ -93,10 +106,10 @@ _tar: | sed -e "s@/\./@/@g" \ ) >> "$$LIST" ; \ done ; \ - echo creating tar file $$ADIR$$NAME.tar.gz... ; \ + echo creating tar file $$ADIR/$$NAME.tar.gz... ; \ export COPYFILE_DISABLE=true ; \ export GZIP="-9v" ; \ - $(TAR) -vczf $$ADIR$$NAME.tar.gz -T "$$LIST" $(TAR_ARGS) ; \ + $(TAR) -czf $$ADIR/$$NAME.tar.gz -T "$$LIST" $(TAR_ARGS) ; \ rm "$$LIST" "$$NAME" @@ -234,20 +247,25 @@ version-date:: update_spec_version:: - @S=$(srcdir)/xscreensaver.spec ; \ + @ \ + S1=$(srcdir)/xscreensaver.spec ; \ + S2=$(srcdir)/debian/changelog ; \ U=$(srcdir)/utils/version.h ; \ VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' < $$U | \ head -1` ; \ - /bin/echo -n "Updating $$S to \"$$VERS\"... " ; \ T=/tmp/xs.$$$$ ; \ - sed "s/^\(%define.version[^0-9]*\)\(.*\)/\1$$VERS/" \ - < $$S > $$T ; \ - if cmp -s $$S $$T ; then \ - echo "unchanged." ; \ - else \ - cat $$T > $$S ; \ - echo "done." ; \ - fi ; \ + for F in "$$S1" "$$S2" ; do \ + /bin/echo -n "Updating $$F to \"$$VERS\"... " ; \ + sed -e "s/^\(%define.version[^0-9]*\)\(.*\)/\1$$VERS/" \ + -e "s/([-0-9.]*)/($$VERS-1)/" \ + < "$$F" > "$$T" ; \ + if cmp -s "$$F" "$$T" ; then \ + echo "unchanged." ; \ + else \ + cat "$$T" > "$$F" ; \ + echo "done." ; \ + fi ; \ + done ; \ rm $$T rpm:: @@ -259,7 +277,7 @@ rpm:: ADIR=archive/ ; \ TGZ=xscreensaver-$$VERS.tar.gz ; \ if [ ! -f $${ADIR}$$TGZ ]; then \ - echo "$${ADIR}$$TGZ does not exist! Did you forget to \`make tar'?" ; \ + echo "$${ADIR}$$TGZ does not exist: do 'make tar' first." ; \ exit 1 ; \ fi ; \ rm -rf /var/tmp/xscreensaver-$$VERS-root ; \ @@ -284,6 +302,39 @@ rpm:: echo '' ; \ ls -lFG xscreensaver*-$$VERS-*.rpm +deb:: + @ \ + VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' utils/version.h | \ + head -1` ; \ + DIR=debian/build ; \ + ADIR=archive/ ; \ + TGZ=xscreensaver-$$VERS.tar.gz ; \ + TGZ2=xscreensaver_$$VERS.orig.tar.gz ; \ + if [ ! -f $${ADIR}$$TGZ ]; then \ + echo "$${ADIR}$$TGZ does not exist: do 'make tar' first." ; \ + exit 1 ; \ + fi ; \ + \ + set -e ; \ + set -x ; \ + rm -rf $$DIR ; \ + mkdir $$DIR ; \ + cp -p "$${ADIR}$$TGZ" "$$DIR/$$TGZ2" ; \ + \ + ( cd $$DIR ; \ + $(TAR) -zxf "$$TGZ2" ; \ + cd xscreensaver-$$VERS ; \ + dpkg-buildpackage -us -uc ; \ + ) ; \ + set +x ; \ + echo '' ; \ + echo 'DEB build complete' ; \ + echo '' ; \ + rm -rf "$$DIR/xscreensaver-$$VERS" ; \ + rm -f "$$DIR/$$TGZ2" ; \ + echo '' ; \ + ls -lFGd "$$DIR/xscreensaver"* + dmg:: $(MAKE2) -C OSX release dmg apk:: diff --git a/README b/README index 9fc2c3151..c01d09e0d 100644 --- a/README +++ b/README @@ -41,6 +41,8 @@ To compile for a Unix system with X11: libxinerama libxrandr libxxf86vm libgl libglu libgle libgtk-3 libgdk-pixbuf2.0 libjpeg libxml2 libpam libsystemd elogind libwayland + You can build a package-manager version with "make rpm" or "make deb". + BSD systems might need gmake instead of make. diff --git a/configure b/configure index cf06a858e..43c26b73b 100755 --- a/configure +++ b/configure @@ -786,6 +786,7 @@ X_LIBS X_PRE_LIBS X_CFLAGS XMKMF +TAR PERL SET_MAKE INSTALL_DATA @@ -5678,11 +5679,63 @@ printf "%s\n" "$ac_cv_perl_version" >&6; } PERL_VERSION=$ac_cv_perl_version fi +for ac_prog in gnutar tar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_TAR+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) case $TAR in + [\\/]* | ?:[\\/]*) + ac_cv_path_TAR="$TAR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_TAR="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac ;; +esac +fi +TAR=$ac_cv_path_TAR +if test -n "$TAR"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TAR" >&5 +printf "%s\n" "$TAR" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + test -n "$TAR" && break +done + if test -z "$PERL" ; then # don't let it be blank... PERL=/usr/bin/perl fi +if test -z "$TAR" ; then TAR=tar ; fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for X" >&5 printf %s "checking for X... " >&6; } diff --git a/configure.ac b/configure.ac index 4f3231a1a..d89e20817 100644 --- a/configure.ac +++ b/configure.ac @@ -478,6 +478,8 @@ AC_DEFUN([AC_PROG_PERL], fi ]) +AC_DEFUN([AC_PROG_TAR], [AC_PATH_PROGS(TAR, [gnutar tar],,)]) + ############################################################################### # @@ -1076,12 +1078,15 @@ AC_CHECK_GETIFADDRS AC_TYPE_SOCKLEN_T AC_CHECK_HEADERS(crypt.h sys/select.h) AC_PROG_PERL +AC_PROG_TAR if test -z "$PERL" ; then # don't let it be blank... PERL=/usr/bin/perl fi +if test -z "$TAR" ; then TAR=tar ; fi + AC_PATH_XTRA if test "$have_x" != yes; then @@ -1123,7 +1128,6 @@ if test -z "$pkg_config" ; then pkg_config="false" fi - # Utility function for running pkg-config-based tests... # pkgs='' @@ -4592,6 +4596,7 @@ AC_SUBST(DEPEND) AC_SUBST(DEPEND_FLAGS) AC_SUBST(DEPEND_DEFINES) AC_SUBST(PERL) +AC_SUBST(TAR) AC_CONFIG_FILES([Makefile utils/Makefile diff --git a/debian/README b/debian/README new file mode 100644 index 000000000..17172a964 --- /dev/null +++ b/debian/README @@ -0,0 +1,17 @@ +Here is a build config for Debian that packages XScreenSaver the correct way. + +The way Debian packages XScreenSaver is an absolute atrocity: it divides it +into half a dozen sub-packages, ensuring that some users will accidentally +end up with a half-installed, nonfunctional installation of XScreenSaver. +XScreenSaver is a single software package. That is how I wrote it, how I +test it, and how it should be distributed. I have been asking them to +change this for years and they refuse. + + -- jwz + +To build a .deb file, do this in the root of the xscreensaver tree: + + make tar + make deb + +Files will appear in debian/build/ diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 000000000..927b6d57c --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +xscreensaver (6.13-1) unstable; urgency=medium + + * Splitting this into multiple packages is a support nightmare, please don't. + + -- Jamie Zawinski Mon, 11 Aug 2025 16:28:39 -0700 diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..860266f75 --- /dev/null +++ b/debian/control @@ -0,0 +1,57 @@ +Source: xscreensaver +Section: x11 +Priority: optional +Maintainer: Jamie Zawinski +Build-Depends: debhelper-compat (= 13), + autotools-dev, + perl, + pkg-config, + gettext, + intltool, + libx11-dev, + libxext-dev, + libxi-dev, + libxt-dev, + libxft-dev, + libxinerama-dev, + libxrandr-dev, + libxxf86vm-dev, + libgl-dev, + libglu-dev, + libgle-dev, + libgtk-3-dev, + libgdk-pixbuf2.0-dev, + libjpeg-dev, + libxml2-dev, + libpam-dev, + libsystemd-dev, + libwayland-dev +Standards-Version: 4.6.2 +Homepage: https://www.jwz.org/xscreensaver/ +Rules-Requires-Root: no + +Package: xscreensaver +Architecture: any +Depends: ${misc:Depends}, + ${shlibs:Depends}, + attr | xattr, + perl +Recommends: miscfiles | wordlist, + fonts-urw-base35 | xfonts-100dpi +Suggests: gdm3 | kdm-gdmcompat, + qcam | streamer, + www-browser, + xdaliclock +Breaks: xscreensaver-gl, + xscreensaver-data, + xscreensaver-data-extra, + xscreensaver-gl-extra, + xscreensaver-screensaver-webcollage, + xscreensaver-screensaver-bsod +Replaces: xscreensaver-gl, + xscreensaver-data, + xscreensaver-data-extra, + xscreensaver-gl-extra, + xscreensaver-screensaver-webcollage, + xscreensaver-screensaver-bsod +Description: XScreenSaver is screen saver and locker for X11. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 000000000..110285d3a --- /dev/null +++ b/debian/copyright @@ -0,0 +1,15 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: XScreenSaver +Upstream-Contact: Jamie Zawinski +Source: https://www.jwz.org/xscreensaver/ + +Files: * +Copyright: 1991-2025 Jamie Zawinski +License: Other_1 + 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. diff --git a/debian/docs b/debian/docs new file mode 100644 index 000000000..66c58a8ce --- /dev/null +++ b/debian/docs @@ -0,0 +1,2 @@ +README +README.hacking diff --git a/debian/postinst b/debian/postinst new file mode 100755 index 000000000..59b225450 --- /dev/null +++ b/debian/postinst @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e + +case "$1" in + configure) + killall -HUP xscreensaver 2>&- + ;; +esac diff --git a/debian/prerm b/debian/prerm new file mode 100755 index 000000000..be913067a --- /dev/null +++ b/debian/prerm @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e + +case "$1" in + remove|purge) + killall -q /usr/bin/xscreensaver || true + ;; +esac diff --git a/debian/rules b/debian/rules new file mode 100755 index 000000000..1ec5bc89f --- /dev/null +++ b/debian/rules @@ -0,0 +1,19 @@ +#!/usr/bin/make -f + +DH_VERBOSE = 1 +export DH_OPTIONS=-v + +%: + dh $@ --without autoreconf + +override_dh_auto_configure: + ./configure --prefix=/usr + +override_dh_installdirs: + dh_installdirs + mkdir -p debian/xscreensaver/etc/pam.d + +override_dh_fixperms-arch: + dh_fixperms + chmod 4755 debian/xscreensaver/usr/libexec/xscreensaver/xscreensaver-auth + chmod 4755 debian/xscreensaver/usr/libexec/xscreensaver/sonar diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 000000000..163aaf8d8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/watch b/debian/watch new file mode 100644 index 000000000..a1355c88e --- /dev/null +++ b/debian/watch @@ -0,0 +1,2 @@ +version=4 +https://www.jwz.org/xscreensaver/download.html xscreensaver-(.*)\.tar\.gz From a3167d7d17e4c70999b6710e5a37e63316c99be6 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 17:00:46 +0200 Subject: [PATCH 07/25] make: Add xattr detection --- config.h.in | 6 ++++++ configure | 43 +++++++++++++++++++++++++++++++++++++++++++ configure.ac | 18 ++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/config.h.in b/config.h.in index 94f888e12..af949bb50 100644 --- a/config.h.in +++ b/config.h.in @@ -90,6 +90,9 @@ /* Define to 1 if you have the 'getwd' function. */ #undef HAVE_GETWD +/* Define to 1 if you have the 'getxattr' function. */ +#undef HAVE_GETXATTR + /* Define this if you have OpenGL. */ #undef HAVE_GL @@ -385,6 +388,9 @@ backward compatibility; new code need not use it. */ #undef STDC_HEADERS +/* Define if xattr functions take additional arguments (macOS) */ +#undef XATTR_ADDITIONAL_OPTIONS + /* Stare into the void. */ #undef XPointer diff --git a/configure b/configure index 43c26b73b..c1c80c3d5 100755 --- a/configure +++ b/configure @@ -5388,6 +5388,49 @@ then : fi +ac_fn_c_check_func "$LINENO" "getxattr" "ac_cv_func_getxattr" +if test "x$ac_cv_func_getxattr" = xyes +then : + printf "%s\n" "#define HAVE_GETXATTR 1" >>confdefs.h + +fi + + if test "$ac_cv_func_getxattr" = yes ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getxattr extra args" >&5 +printf %s "checking for getxattr extra args... " >&6; } +if test ${ac_cv_xattr_extra_args+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +getxattr("", "", "", 0, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_xattr_extra_args=yes +else case e in #( + e) ac_cv_xattr_extra_args=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_xattr_extra_args" >&5 +printf "%s\n" "$ac_cv_xattr_extra_args" >&6; } + if test "$ac_cv_xattr_extra_args" = yes; then + +printf "%s\n" "#define XATTR_ADDITIONAL_OPTIONS 1" >>confdefs.h + + fi + fi ac_fn_c_check_member "$LINENO" "struct sockaddr" "sa_len" "ac_cv_member_struct_sockaddr_sa_len" "#include " if test "x$ac_cv_member_struct_sockaddr_sa_len" = xyes diff --git a/configure.ac b/configure.ac index d89e20817..e03d035d0 100644 --- a/configure.ac +++ b/configure.ac @@ -878,6 +878,23 @@ AC_DEFUN([AC_TYPE_SOCKLEN_T], [Define to `int' if or does not define.]) fi]) +AC_DEFUN([AC_CHECK_XATTR], + [AC_CHECK_FUNCS(getxattr) + if test "$ac_cv_func_getxattr" = yes ; then + AC_CACHE_CHECK([for getxattr extra args], ac_cv_xattr_extra_args, + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [#include ], + [getxattr("", "", "", 0, 0, 0);])], + [ac_cv_xattr_extra_args=yes], + [ac_cv_xattr_extra_args=no])]) + if test "$ac_cv_xattr_extra_args" = yes; then + AC_DEFINE(XATTR_ADDITIONAL_OPTIONS, 1, + [Define if xattr functions take additional arguments (macOS)]) + fi] + fi) + + ############################################################################### # # Some utility functions to make checking for X things easier. @@ -1071,6 +1088,7 @@ AC_CHECK_FUNCS(select fcntl uname nice setpriority getcwd getwd putenv sbrk) AC_CHECK_FUNCS(sigaction syslog realpath setrlimit) AC_CHECK_FUNCS(setlocale sqrtf) AC_CHECK_FUNCS(getaddrinfo) +AC_CHECK_XATTR AC_CHECK_MEMBERS([struct sockaddr.sa_len],,, [#include ]) AC_CHECK_ICMP AC_CHECK_ICMPHDR From 349d6895f66d8b8fc55f2242051def1b8d7e807c Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:06:49 +0200 Subject: [PATCH 08/25] hacks/xss-getimage: store url/title in xattrs --- hacks/xscreensaver-getimage-file | 72 +++++++++++++++++++++++++++++-- hacks/xscreensaver-getimage.c | 61 +++++++++++++++++++++++--- utils/grabclient.c | 74 +++++++++++++++++++++++++++----- 3 files changed, 187 insertions(+), 20 deletions(-) diff --git a/hacks/xscreensaver-getimage-file b/hacks/xscreensaver-getimage-file index 7172247b2..5f693447a 100755 --- a/hacks/xscreensaver-getimage-file +++ b/hacks/xscreensaver-getimage-file @@ -53,7 +53,7 @@ BEGIN { eval 'use LWP::Simple; use LWP::UserAgent;' } my $progname = $0; $progname =~ s@.*/@@g; -my ($version) = ('$Revision: 1.70 $' =~ m/\s(\d[.\d]+)\s/s); +my ($version) = ('$Revision: 1.71 $' =~ m/\s(\d[.\d]+)\s/s); my $verbose = 0; @@ -102,6 +102,7 @@ my $min_image_height = 500; my @all_files = (); # list of "good" files we've collected my %seen_inodes; # for breaking recursive symlink loops +my $setfattr = 'setfattr'; # For diagnostic messages: # @@ -113,6 +114,17 @@ my $skip_count_stat = 0; # number of files skipped after stat my $config_file = $ENV{HOME} . "/.xscreensaver"; my $image_directory = undef; +sub which($) { + my ($cmd) = @_; + if ($cmd =~ m@^\./|^/@) { + return undef unless (-x $cmd); + } + foreach my $dir (split (/:/, $ENV{PATH})) { + my $cmd2 = "$dir/$cmd"; + return $cmd2 if (-x "$cmd2"); + } + return undef; +} sub find_all_files($); sub find_all_files($) { @@ -532,9 +544,17 @@ sub parse_feed($) { foreach my $item (@items) { my $iurl = undef; + my $title = undef; my $id = undef; my $kind = '?'; + ($title) = ($item =~ m@]*>(.*?)@si); + if ($title) { + $title =~ s/<.*?>//gs; + $title = html_unquote ($title); + $title =~ s/^\s+|\s+$//gs; + } + # The container groups the same content in different # representations. So first, edit each of those to contain only the # highest resolution child. @@ -668,7 +688,7 @@ sub parse_feed($) { my $o = $ids{$id}; if (! $o) { $ids{$id} = $iurl; - my @P = ($iurl, $id); + my @P = ($iurl, $id, $title); push @imgs, \@P; print STDERR "$progname: $kind: $iurl\n" if ($verbose > 4); } elsif ($iurl ne $o) { @@ -1059,6 +1079,47 @@ sub download_image($$$) { } +# Write some xattrs on the file saying where we downloaded it from: +# "user.xdg.origin.url" and "user.dublincore.title". +# +sub store_xattrs($$$) { + my ($file, $url, $title) = @_; + + # Sometimes we have 'setfattr', sometimes 'xattr', sometimes neither. + # And they take different command-line options. Yay! + # + # Also, the macOS and Linux versions of 'xattr' have similar but not + # identical options (but close enough for our purposes). The macOS + # version is a binary while the Linux version is a Python script. + # Mac weirdness is due to resource forks. + # + # What about BSD? Solaris? Who knows! + # + # There's also the File::ExtAttr perl module, but it is not installed + # by default, so using that would not improve matters in any way. + + return unless $setfattr; + + if ($url) { + my $key = 'user.xdg.origin.url'; + my @cmd = ($setfattr =~ m/setfattr/ + ? ($setfattr, '-n', $key, '-v', $url, $file) # setfattr + : ($setfattr, '-w', $key, $url, $file)); # xattr + print STDERR "$progname: exec: @cmd\n" if ($verbose); + system (@cmd); # Ignore errors + } + + if ($title) { + my $key = 'user.dublincore.title'; + my @cmd = ($setfattr =~ m/setfattr/ + ? ($setfattr, '-n', $key, '-v', $title, $file) # setfattr + : ($setfattr, '-w', $key, $title, $file)); # xattr + print STDERR "$progname: exec: @cmd\n" if ($verbose); + system (@cmd); # Ignore errors + } +} + + sub mirror_feed($) { my ($url) = @_; @@ -1144,9 +1205,12 @@ sub mirror_feed($) { my @urls = parse_feed ($url); print STDERR "$progname: " . ($#urls + 1) . " images\n" if ($verbose > 1); + + $setfattr = which ('setfattr') || which ('xattr'); + my %seen_src_urls; foreach my $p (@urls) { - my ($furl, $id) = @$p; + my ($furl, $id, $title) = @$p; $furl = expand_url ($furl, $url); # No need to download the same image twice, even if it was in the feed @@ -1158,6 +1222,8 @@ sub mirror_feed($) { next unless $f; $files{$f} = 1; # Got it, don't delete $count++; + + store_xattrs ("$dir/$f", $furl, $title); } my $empty_p = ($count <= 0); diff --git a/hacks/xscreensaver-getimage.c b/hacks/xscreensaver-getimage.c index 39eb8722a..29a2cb925 100644 --- a/hacks/xscreensaver-getimage.c +++ b/hacks/xscreensaver-getimage.c @@ -144,6 +144,10 @@ # include /* for waitpid() and associated macros */ #endif +#ifdef HAVE_GETXATTR +# include +#endif + #include "version.h" #include "../driver/blurb.h" #include "yarandom.h" @@ -1902,6 +1906,40 @@ drawable_miniscule_p (Display *dpy, Drawable drawable) } +/* Returns the URL and title of the given file, if present in xattrs. + Duplicated in grabclient.c. + */ +static void +get_file_xattrs (const char *file, char **urlP, char **titleP) +{ +# ifdef HAVE_GETXATTR + +# ifdef XATTR_ADDITIONAL_OPTIONS +# define GETXATTR(F,K,B,S) getxattr (F, K, B, S, 0, 0) +# else +# define GETXATTR(F,K,B,S) getxattr (F, K, B, S) +# endif + + char url[1024], title[1024]; + ssize_t s; + + s = GETXATTR (file, "user.xdg.origin.url", url, sizeof(url)-1); + if (s > 0) + { + url[s] = 0; + *urlP = strdup (url); + } + + s = GETXATTR (file, "user.dublincore.title", title, sizeof(title)-1); + if (s > 0) + { + title[s] = 0; + *titleP = strdup (title); + } +# endif /* HAVE_GETXATTR */ +} + + /* Grabs an image (from a file, video, or the desktop) and renders it on the Drawable. If 'file' is specified, always use that file. Otherwise, select randomly, based on the other arguments. @@ -1921,6 +1959,8 @@ get_image (Screen *screen, grab_type which = GRAB_BARS; struct stat st; const char *file_prop = 0; + char *xattr_url = 0; + char *xattr_title = 0; char *absfile = 0; XRectangle geom = { 0, 0, 0, 0 }; @@ -2081,6 +2121,7 @@ get_image (Screen *screen, verbose_p, &geom)) goto COLORBARS; file_prop = file; + get_file_xattrs (file, &xattr_url, &xattr_title); break; case GRAB_VIDEO: @@ -2096,7 +2137,10 @@ get_image (Screen *screen, { Atom a = XInternAtom (dpy, XA_XSCREENSAVER_IMAGE_FILENAME, False); - if (file_prop && *file_prop) + if (xattr_url) + XChangeProperty (dpy, window, a, XA_STRING, 8, PropModeReplace, + (unsigned char *) xattr_url, strlen(xattr_url)); + else if (file_prop && *file_prop) { char *f2 = strdup (file_prop); @@ -2105,11 +2149,6 @@ get_image (Screen *screen, char *slash = strrchr (f2, '/'); char *dot = strrchr ((slash ? slash : f2), '.'); if (dot) *dot = 0; - /* Replace slashes with newlines */ - /* while ((dot = strchr(f2, '/'))) *dot = '\n'; */ - /* Replace slashes with spaces */ - /* while ((dot = strchr(f2, '/'))) *dot = ' '; */ - XChangeProperty (dpy, window, a, XA_STRING, 8, PropModeReplace, (unsigned char *) f2, strlen(f2)); free (f2); @@ -2117,6 +2156,13 @@ get_image (Screen *screen, else XDeleteProperty (dpy, window, a); + a = XInternAtom (dpy, XA_XSCREENSAVER_IMAGE_TITLE, False); + if (xattr_title) + XChangeProperty (dpy, window, a, XA_STRING, 8, PropModeReplace, + (unsigned char *) xattr_title, strlen(xattr_title)); + else + XDeleteProperty (dpy, window, a); + a = XInternAtom (dpy, XA_XSCREENSAVER_IMAGE_GEOMETRY, False); if (geom.width > 0) { @@ -2132,6 +2178,9 @@ get_image (Screen *screen, if (absfile) free (absfile); XSync (dpy, False); + + if (xattr_url) free (xattr_url); + if (xattr_title) free (xattr_title); } diff --git a/utils/grabclient.c b/utils/grabclient.c index 561d4ba34..661ea26c4 100644 --- a/utils/grabclient.c +++ b/utils/grabclient.c @@ -107,6 +107,9 @@ #ifdef HAVE_SYS_WAIT_H # include /* for waitpid() and associated macros */ #endif +#ifdef HAVE_GETXATTR +# include +#endif extern char *progname; @@ -243,7 +246,7 @@ get_name_from_xprops (Display *dpy, Window window) int format; unsigned long nitems, bytesafter; unsigned char *name = 0; - Atom atom = XInternAtom (dpy, XA_XSCREENSAVER_IMAGE_FILENAME, False); + Atom atom = XInternAtom (dpy, XA_XSCREENSAVER_IMAGE_TITLE, False); if (XGetWindowProperty (dpy, window, atom, 0, 1024, False, XA_STRING, &type, &format, &nitems, &bytesafter, @@ -251,8 +254,17 @@ get_name_from_xprops (Display *dpy, Window window) == Success && type != None) return (char *) name; - else - return 0; + + atom = XInternAtom (dpy, XA_XSCREENSAVER_IMAGE_FILENAME, False); + if (XGetWindowProperty (dpy, window, atom, + 0, 1024, False, XA_STRING, + &type, &format, &nitems, &bytesafter, + &name) + == Success + && type != None) + return (char *) name; + + return 0; } @@ -577,6 +589,40 @@ open_image_name_pipe (const char *dir) } +/* Returns the URL and title of the given file, if present in xattrs. + Duplicated in xscreensaver-getimage.c. + */ +static void +get_file_xattrs (const char *file, char **urlP, char **titleP) +{ +# ifdef HAVE_GETXATTR + +# ifdef XATTR_ADDITIONAL_OPTIONS +# define GETXATTR(F,K,B,S) getxattr (F, K, B, S, 0, 0) +# else +# define GETXATTR(F,K,B,S) getxattr (F, K, B, S) +# endif + + char url[1024], title[1024]; + ssize_t s; + + s = GETXATTR (file, "user.xdg.origin.url", url, sizeof(url)-1); + if (s > 0) + { + url[s] = 0; + *urlP = strdup (url); + } + + s = GETXATTR (file, "user.dublincore.title", title, sizeof(title)-1); + if (s > 0) + { + title[s] = 0; + *titleP = strdup (title); + } +# endif /* HAVE_GETXATTR */ +} + + static void xscreensaver_getimage_file_cb (XtPointer closure, int *source, XtInputId *id) { @@ -587,6 +633,8 @@ xscreensaver_getimage_file_cb (XtPointer closure, int *source, XtInputId *id) const char *dir = clo2->directory; char *absfile = 0; int i = 0; + char *xattr_url = 0; + char *xattr_title = 0; *buf = 0; do { @@ -650,20 +698,24 @@ xscreensaver_getimage_file_cb (XtPointer closure, int *source, XtInputId *id) geom.height = h; } - /* Take the extension off of the file name. */ - /* Duplicated in driver/xscreensaver-getimage.c. */ - if (*buf) + get_file_xattrs ((absfile ? absfile : buf), &xattr_url, &xattr_title); + if (xattr_title) + sprintf (buf, "%.100s", xattr_title); + else if (xattr_url) + sprintf (buf, "%.100s", xattr_url); + else if (*buf) { + /* Take the extension off of the file name. */ + /* Duplicated in driver/xscreensaver-getimage.c. */ char *slash = strrchr (buf, '/'); char *dot = strrchr ((slash ? slash : buf), '.'); if (dot) *dot = 0; - /* Replace slashes with newlines */ - /* while (dot = strchr(buf, '/')) *dot = '\n'; */ - /* Replace slashes with spaces */ - /* while ((dot = strchr(buf, '/'))) *dot = ' '; */ } - if (absfile) free (absfile); + if (xattr_title) free (xattr_title); + if (xattr_url) free (xattr_url); + if (absfile) free (absfile); + clo2->callback (clo2->screen, clo2->window, clo2->drawable, buf, &geom, clo2->closure); clo2->callback = 0; From 2271906027809a7031da6c6a489dc1e59d77a071 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 17:15:40 +0200 Subject: [PATCH 09/25] ? Fix Wayland support Ran out of time trying to figure this one out, pushed all Wayland-touching code into this commit --- configure | 3 + configure.ac | 3 + driver/Makefile.in | 114 +- driver/demo-Gtk.c | 169 +- driver/test-wayland-lock.c | 160 ++ driver/wayland-dpms.c | 64 +- driver/wayland-dpy.c | 2 +- driver/wayland-dpy.h | 1 + driver/wayland-idle.c | 45 +- driver/wayland-lock.h | 41 + .../ext-session-lock-v1-client-protocol.h | 684 +++++ .../ext-session-lock-v1-protocol.c | 97 + .../wayland-protocols/ext-session-lock-v1.xml | 328 +++ .../xdg-shell-v1-client-protocol.h | 2381 ----------------- .../wayland-protocols/xdg-shell-v1-protocol.c | 184 -- driver/wayland-protocols/xdg-shell.xml | 1415 ---------- 16 files changed, 1581 insertions(+), 4110 deletions(-) create mode 100644 driver/test-wayland-lock.c create mode 100644 driver/wayland-lock.h create mode 100644 driver/wayland-protocols/ext-session-lock-v1-client-protocol.h create mode 100644 driver/wayland-protocols/ext-session-lock-v1-protocol.c create mode 100644 driver/wayland-protocols/ext-session-lock-v1.xml delete mode 100644 driver/wayland-protocols/xdg-shell-v1-client-protocol.h delete mode 100644 driver/wayland-protocols/xdg-shell-v1-protocol.c delete mode 100644 driver/wayland-protocols/xdg-shell.xml diff --git a/configure b/configure index c1c80c3d5..dae42b5b9 100755 --- a/configure +++ b/configure @@ -688,6 +688,7 @@ SETUID_HACKS SETUID_AUTH PROG_SETCAP WAYLAND_GTK_OBJS +WAYLAND_LOCK_OBJS WAYLAND_DPMS_OBJS WAYLAND_IDLE_OBJS WAYLAND_DPY_OBJS @@ -13630,6 +13631,7 @@ printf "%s\n" "$ac_cv_wayland_config_libs" >&6; } WAYLAND_DPY_OBJS="" WAYLAND_IDLE_OBJS="" WAYLAND_DPMS_OBJS="" + WAYLAND_LOCK_OBJS="" WAYLAND_GTK_OBJS="" if test "$have_wayland" = yes; then WAYLAND_DATADIR=`$pkg_config --variable=prefix wayland-client` @@ -13638,6 +13640,7 @@ printf "%s\n" "$ac_cv_wayland_config_libs" >&6; } WAYLAND_DPY_OBJS='$(WAYLAND_DPY_OBJS_1)' WAYLAND_IDLE_OBJS='$(WAYLAND_IDLE_OBJS_1)' WAYLAND_DPMS_OBJS='$(WAYLAND_DPMS_OBJS_1)' + WAYLAND_LOCK_OBJS='$(WAYLAND_LOCK_OBJS_1)' WAYLAND_GTK_OBJS='$(WAYLAND_GTK_OBJS_1)' fi diff --git a/configure.ac b/configure.ac index e03d035d0..6968fadf5 100644 --- a/configure.ac +++ b/configure.ac @@ -2261,6 +2261,7 @@ if test "$with_wayland" = yes; then WAYLAND_DPY_OBJS="" WAYLAND_IDLE_OBJS="" WAYLAND_DPMS_OBJS="" + WAYLAND_LOCK_OBJS="" WAYLAND_GTK_OBJS="" if test "$have_wayland" = yes; then WAYLAND_DATADIR=`$pkg_config --variable=prefix wayland-client` @@ -2269,6 +2270,7 @@ if test "$with_wayland" = yes; then WAYLAND_DPY_OBJS='$(WAYLAND_DPY_OBJS_1)' WAYLAND_IDLE_OBJS='$(WAYLAND_IDLE_OBJS_1)' WAYLAND_DPMS_OBJS='$(WAYLAND_DPMS_OBJS_1)' + WAYLAND_LOCK_OBJS='$(WAYLAND_LOCK_OBJS_1)' WAYLAND_GTK_OBJS='$(WAYLAND_GTK_OBJS_1)' fi @@ -4552,6 +4554,7 @@ AC_SUBST(WAYLAND_GEN) AC_SUBST(WAYLAND_DPY_OBJS) AC_SUBST(WAYLAND_IDLE_OBJS) AC_SUBST(WAYLAND_DPMS_OBJS) +AC_SUBST(WAYLAND_LOCK_OBJS) AC_SUBST(WAYLAND_GTK_OBJS) AC_SUBST(PROG_SETCAP) AC_SUBST(SETUID_AUTH) diff --git a/driver/Makefile.in b/driver/Makefile.in index b5680ec47..db7dd8768 100644 --- a/driver/Makefile.in +++ b/driver/Makefile.in @@ -39,23 +39,23 @@ WAYLAND_DATADIR = @WAYLAND_DATADIR@ WAYLAND_GEN = @WAYLAND_GEN@ WAYLAND_PROTO = wayland-protocols -WAYLAND_GEN_XML = $(WAYLAND_PROTO)/xdg-shell.xml \ - $(WAYLAND_PROTO)/ext-idle-notify-v1.xml \ +WAYLAND_GEN_XML = $(WAYLAND_PROTO)/ext-idle-notify-v1.xml \ $(WAYLAND_PROTO)/idle.xml \ $(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1.xml \ - $(WAYLAND_PROTO)/dpms.xml + $(WAYLAND_PROTO)/dpms.xml \ + $(WAYLAND_PROTO)/ext-session-lock-v1.xml -WAYLAND_GEN_HDRS = $(WAYLAND_PROTO)/xdg-shell-v1-client-protocol.h \ - $(WAYLAND_PROTO)/ext-idle-notify-v1-client-protocol.h \ +WAYLAND_GEN_HDRS = $(WAYLAND_PROTO)/ext-idle-notify-v1-client-protocol.h \ $(WAYLAND_PROTO)/idle-client-protocol.h \ $(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-client-protocol.h \ - $(WAYLAND_PROTO)/dpms-client-protocol.h + $(WAYLAND_PROTO)/dpms-client-protocol.h \ + $(WAYLAND_PROTO)/ext-session-lock-v1-client-protocol.h -WAYLAND_GEN_SRCS = $(WAYLAND_PROTO)/xdg-shell-v1-protocol.c \ - $(WAYLAND_PROTO)/ext-idle-notify-v1-protocol.c \ +WAYLAND_GEN_SRCS = $(WAYLAND_PROTO)/ext-idle-notify-v1-protocol.c \ $(WAYLAND_PROTO)/idle-protocol.c \ $(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-protocol.c \ - $(WAYLAND_PROTO)/dpms-protocol.c + $(WAYLAND_PROTO)/dpms-protocol.c \ + $(WAYLAND_PROTO)/ext-session-lock-v1-protocol.c WAYLAND_DPY_OBJS = @WAYLAND_DPY_OBJS@ WAYLAND_DPY_SRCS = wayland-dpy.c @@ -73,6 +73,11 @@ WAYLAND_DPMS_OBJS_1 = wayland-dpms.o \ $(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-protocol.o \ $(WAYLAND_PROTO)/dpms-protocol.o +WAYLAND_LOCK_OBJS = @WAYLAND_LOCK_OBJS@ +WAYLAND_LOCK_SRCS = wayland-lock.c +WAYLAND_LOCK_OBJS_1 = wayland-lock.o \ + $(WAYLAND_PROTO)/ext-session-lock-v1-protocol.o + WAYLAND_GTK_OBJS = @WAYLAND_GTK_OBJS@ WAYLAND_GTK_SRCS = wayland-dpms.c WAYLAND_GTK_OBJS_1 = $(WAYLAND_DPY_OBJS) $(WAYLAND_IDLE_OBJS) \ @@ -156,7 +161,7 @@ GFX_DEFS = @GL_CFLAGS@ -DLOCALEDIR=\"$(localedir)\" SUBP_DEFS = @GL_CFLAGS@ GFX_SRCS = xscreensaver-gfx.c screens.c windows.c subprocs.c \ exec.c prefsw.c dpms.c fade.c exts.c atomswm.c \ - $(WAYLAND_DPY_SRCS) $(WAYLAND_DPMS_SRCS) + $(WAYLAND_DPMS_SRCS) GFX_OBJS = xscreensaver-gfx.o screens.o windows.o subprocs.o \ exec.o prefsw.o dpms.o fade.o exts.o atomswm.o \ prefs.o blurb.o atoms.o clientmsg.o xinput.o \ @@ -256,11 +261,11 @@ MOTIF_LIBS = $(LIBS_PRE) $(XDPMS_LIBS) $(XDPMS_LIBS) @MOTIF_LIBS@ \ TEST_SRCS = test-passwd.c test-uid.c test-xdpms.c test-grab.c \ test-fade.c test-xinerama.c test-vp.c test-randr.c \ xdpyinfo.c test-screens.c test-yarandom.c test-xinput.c \ - test-xkb.c + test-xkb.c test-wayland-lock.c TEST_EXES = test-passwd test-uid test-xdpms test-grab \ test-fade test-xinerama test-vp test-randr \ xdpyinfo test-screens test-yarandom test-xinput \ - test-xkb + test-xkb test-wayland-lock EXES = xscreensaver xscreensaver-command xscreensaver-settings UTIL_EXES = xscreensaver-gfx @EXES_SYSTEMD@ @@ -273,7 +278,7 @@ HDRS = XScreenSaver_ad.h XScreenSaver_Xm_ad.h \ xscreensaver.h prefs.h remote.h exec.h \ demo-Gtk-conf.h auth.h types.h blurb.h atoms.h clientmsg.h \ screens.h xinput.h fade.h wayland-dpy.h wayland-dpyI.h \ - wayland-idle.h wayland-dpms.h \ + wayland-idle.h wayland-dpms.h wayland-lock.h \ $(WAYLAND_GEN_HDRS) MENA = xscreensaver.man xscreensaver-settings.man \ xscreensaver-command.man @@ -1005,30 +1010,16 @@ XScreenSaver_Xm_ad.h:: # need to run "wayland-scanner". But we print a warning if the system's # XML files exist and differ from our own. -# "xdg-shell" isn't used yet but probably will be. -# -$(srcdir)/$(WAYLAND_PROTO)/xdg-shell.xml:: - @\ - F=$(WAYLAND_DATADIR)/wayland-protocols/stable/xdg-shell/xdg-shell.xml ; \ - if [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \ - echo "WARNING: $$F and $@ differ" >&2 ; \ - fi -$(srcdir)/$(WAYLAND_PROTO)/xdg-shell-v1-client-protocol.h: \ -$(srcdir)/$(WAYLAND_PROTO)/xdg-shell.xml - wayland-scanner client-header < $< > $@ -$(srcdir)/$(WAYLAND_PROTO)/xdg-shell-v1-protocol.c: \ -$(srcdir)/$(WAYLAND_PROTO)/xdg-shell.xml - wayland-scanner private-code < $< > $@ -$(WAYLAND_PROTO)/xdg-shell-v1-protocol.o: \ -$(srcdir)/$(WAYLAND_PROTO)/xdg-shell-v1-protocol.c - $(CC) -c $(CC_ALL) $< -o $@ - # "idle-notify-v1" for wayland-idle.c # $(srcdir)/$(WAYLAND_PROTO)/ext-idle-notify-v1.xml:: @\ F=$(WAYLAND_DATADIR)/wayland-protocols/staging/ext-idle-notify/ext-idle-notify-v1.xml ; \ - if [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \ + if ! [ -f "$@" ]; then \ + echo "ERROR: $@ does not exist" >&2 ; \ + echo "consider: cp -p $$F $@" ; \ + exit 1 ; \ + elif [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \ echo "WARNING: $$F and $@ differ" >&2 ; \ fi $(srcdir)/$(WAYLAND_PROTO)/ext-idle-notify-v1-client-protocol.h: \ @@ -1047,7 +1038,11 @@ $(srcdir)/$(WAYLAND_PROTO)/ext-idle-notify-v1-protocol.c $(srcdir)/$(WAYLAND_PROTO)/idle.xml:: @\ F="$(WAYLAND_DATADIR)/plasma-wayland-protocols/idle.xml" ; \ - if [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \ + if ! [ -e "$@" ]; then \ + echo "ERROR: $@ does not exist" >&2 ; \ + echo "consider: cp -p $$F $@" ; \ + exit 1 ; \ + elif [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \ echo "WARNING: $$F and $@ differ" >&2 ; \ fi $(srcdir)/$(WAYLAND_PROTO)/idle-client-protocol.h: \ @@ -1066,7 +1061,11 @@ $(srcdir)/$(WAYLAND_PROTO)/idle-protocol.c $(srcdir)/$(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1.xml:: @\ F="$(WAYLAND_DATADIR)/wayland-protocols/staging/wlr-output-power-management-unstable-v1.xml" ; \ - if [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \ + if ! [ -e "$@" ]; then \ + echo "ERROR: $@ does not exist" >&2 ; \ + echo "consider: cp -p $$F $@" ; \ + exit 1 ; \ + elif [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \ echo "WARNING: $$F and $@ differ" >&2 ; \ fi $(srcdir)/$(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-client-protocol.h: \ @@ -1085,7 +1084,11 @@ $(srcdir)/$(WAYLAND_PROTO)/wlr-output-power-management-unstable-v1-protocol.c $(srcdir)/$(WAYLAND_PROTO)/dpms.xml:: @\ F="$(WAYLAND_DATADIR)/plasma-wayland-protocols/dpms.xml" ; \ - if [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \ + if ! [ -e "$@" ]; then \ + echo "ERROR: $@ does not exist" >&2 ; \ + echo "consider: cp -p $$F $@" ; \ + exit 1 ; \ + elif [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \ echo "WARNING: $$F and $@ differ" >&2 ; \ fi $(srcdir)/$(WAYLAND_PROTO)/dpms-client-protocol.h: \ @@ -1098,6 +1101,27 @@ $(WAYLAND_PROTO)/dpms-protocol.o: \ $(srcdir)/$(WAYLAND_PROTO)/dpms-protocol.c $(CC) -c $(CC_ALL) $< -o $@ +# "ext-session-lock-v1" for wayland-lock.c +# +$(srcdir)/$(WAYLAND_PROTO)/ext-session-lock-v1.xml:: + @\ + F="$(WAYLAND_DATADIR)/wayland-protocols/staging/ext-session-lock/ext-session-lock-v1.xml" ; \ + if ! [ -e "$@" ]; then \ + echo "ERROR: $@ does not exist" >&2 ; \ + echo "consider: cp -p $$F $@" ; \ + exit 1 ; \ + elif [ -e "$$F" ] && ! cmp -s "$$F" $@ ; then \ + echo "WARNING: $$F and $@ differ" >&2 ; \ + fi +$(srcdir)/$(WAYLAND_PROTO)/ext-session-lock-v1-client-protocol.h: \ +$(srcdir)/$(WAYLAND_PROTO)/ext-session-lock-v1.xml + wayland-scanner client-header < $< > $@ +$(srcdir)/$(WAYLAND_PROTO)/ext-session-lock-v1-protocol.c: \ +$(srcdir)/$(WAYLAND_PROTO)/ext-session-lock-v1.xml + wayland-scanner private-code < $< > $@ +$(WAYLAND_PROTO)/ext-session-lock-v1-protocol.o: \ +$(srcdir)/$(WAYLAND_PROTO)/ext-session-lock-v1-protocol.c + $(CC) -c $(CC_ALL) $< -o $@ ############################################################################## @@ -1160,6 +1184,13 @@ test-screens: $(TEST_SCREENS_OBJS) test-yarandom: test-yarandom.o blurb.o $(CC) -DTEST $(LDFLAGS) -o $@ test-yarandom.o blurb.o $(UTILS_BIN)/yarandom.o +TEST_WLOCK_OBJS = test-wayland-lock.o blurb.o atoms.o \ + $(WAYLAND_DPY_OBJS) $(WAYLAND_LOCK_OBJS) \ + $(UTILS_BIN)/visual.o $(UTILS_BIN)/resources.o $(UTILS_BIN)/usleep.o \ + $(UTILS_BIN)/logo.o $(UTILS_BIN)/minixpm.o + +test-wayland-lock: $(TEST_WLOCK_OBJS) + $(CC) $(LDFLAGS) -o $@ $(TEST_WLOCK_OBJS) $(GFX_LIBS) XDPY_DEFS = -DHAVE_GLX $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS) XDPY_LIBS = $(LIBS_PRE) -lGL -lX11 -lXext $(LIBS_POST) @@ -1306,6 +1337,15 @@ test-screens.o: $(UTILS_SRC)/visual.h test-uid.o: ../config.h test-vp.o: $(srcdir)/blurb.h test-vp.o: ../config.h +test-wayland-lock.o: $(srcdir)/atoms.h +test-wayland-lock.o: $(srcdir)/blurb.h +test-wayland-lock.o: ../config.h +test-wayland-lock.o: $(srcdir)/screens.h +test-wayland-lock.o: $(srcdir)/types.h +test-wayland-lock.o: $(UTILS_SRC)/resources.h +test-wayland-lock.o: $(srcdir)/wayland-dpy.h +test-wayland-lock.o: $(srcdir)/wayland-lock.h +test-wayland-lock.o: $(srcdir)/xscreensaver.h test-xdpms.o: $(srcdir)/blurb.h test-xdpms.o: ../config.h test-xinerama.o: $(srcdir)/blurb.h @@ -1326,12 +1366,8 @@ wayland-dpms.o: $(srcdir)/wayland-dpy.h wayland-dpms.o: $(srcdir)/wayland-protocols/dpms-client-protocol.h wayland-dpms.o: $(srcdir)/wayland-protocols/wlr-output-power-management-unstable-v1-client-protocol.h wayland-dpy.o: $(srcdir)/blurb.h -wayland-dpy.o: $(srcdir)/blurb.h -wayland-dpy.o: ../config.h wayland-dpy.o: ../config.h wayland-dpy.o: $(srcdir)/wayland-dpyI.h -wayland-dpy.o: $(srcdir)/wayland-dpyI.h -wayland-dpy.o: $(srcdir)/wayland-dpy.h wayland-dpy.o: $(srcdir)/wayland-dpy.h wayland-idle.o: $(srcdir)/blurb.h wayland-idle.o: ../config.h diff --git a/driver/demo-Gtk.c b/driver/demo-Gtk.c index 6f0727da0..9ab785d13 100644 --- a/driver/demo-Gtk.c +++ b/driver/demo-Gtk.c @@ -128,9 +128,8 @@ typedef struct { Visual *gl_visual; # ifdef HAVE_WAYLAND - wayland_dpy *wayland_dpy; - wayland_idle *wayland_idle; - wayland_dpms *wayland_dpms; + Bool have_wayland_p; + Bool have_wayland_idle_p; # endif conf_data *cdata; /* private data for per-hack configuration */ @@ -139,9 +138,11 @@ typedef struct { Bool initializing_p; /* flag for breaking recursion loops */ Bool flushing_p; /* flag for breaking recursion loops */ Bool saving_p; /* flag for breaking recursion loops */ + Bool locking_supported_p; /* Whether locking is possible */ Bool dpms_supported_p; /* Whether XDPMS is available */ Bool dpms_partial_p; /* Whether DPMS only supports "Off" */ Bool grabbing_supported_p; /* Whether "Grab Desktop" and "Fade" work */ + const char *lock_why, *dpms_why, *grab_why; char *desired_preview_cmd; /* subprocess we intend to run */ char *running_preview_cmd; /* subprocess we are currently running */ @@ -2184,6 +2185,7 @@ file_chooser (GtkWindow *parent, GtkEntry *entry, char **retP, fprintf (stderr, "%s: chooser: default \"%s\"\n", blurb(), p2); } free (p2); + if (! gf) abort(); g_object_unref (gf); } @@ -2395,7 +2397,7 @@ server_current_hack (state *s) &dataP) == Success && type == XA_INTEGER - && nitems >= 3 + && nitems >= 4 && dataP) { PROP32 *data = (PROP32 *) dataP; @@ -2472,6 +2474,7 @@ populate_hack_list (state *s) { model = gtk_list_store_new (COL_LAST, G_TYPE_BOOLEAN, G_TYPE_STRING); g_object_set (G_OBJECT (list), "model", model, NULL); + if (! model) abort(); g_object_unref (model); ren = gtk_cell_renderer_toggle_new (); @@ -2576,16 +2579,20 @@ populate_prefs_page (state *s) XScreenSaverWindow *win = XSCREENSAVER_WINDOW (s->window); saver_preferences *p = &s->prefs; - Bool can_lock_p = TRUE; Bool dpms_full_p; + char *lock_why = 0; # ifdef NO_LOCKING - can_lock_p = FALSE; + s->locking_supported_p = FALSE; + lock_why = _("Not compiled with support for locking"); # endif if (s->backend == WAYLAND_BACKEND || s->backend == XWAYLAND_BACKEND) - can_lock_p = FALSE; + { + s->locking_supported_p = FALSE; + lock_why = _("Locking not supported under Wayland"); + } /* If there is only one screen, the mode menu contains "random" but not "random-same". @@ -2750,9 +2757,17 @@ populate_prefs_page (state *s) /* Blanking and Locking */ - SENSITIZE (lock_button, can_lock_p); - SENSITIZE (lock_spinbutton, can_lock_p && p->lock_p); - SENSITIZE (lock_mlabel, can_lock_p && p->lock_p); + SENSITIZE (lock_button, s->locking_supported_p); + SENSITIZE (lock_spinbutton, s->locking_supported_p && p->lock_p); + SENSITIZE (lock_mlabel, s->locking_supported_p && p->lock_p); + + if (!s->locking_supported_p && lock_why) + { + gtk_widget_set_tooltip_text (win->lock_menuitem, lock_why); + gtk_widget_set_tooltip_text (win->lock_button, lock_why); + gtk_widget_set_tooltip_text (win->lock_spinbutton, lock_why); + gtk_widget_set_tooltip_text (win->lock_mlabel, lock_why); + } /* DPMS */ @@ -2777,12 +2792,36 @@ populate_prefs_page (state *s) s->grabbing_supported_p)); SENSITIZE (fade_spinbutton, ((p->fade_p || p->unfade_p) && s->grabbing_supported_p)); + SENSITIZE (grab_desk_button, (s->grabbing_supported_p)); # undef SENSITIZE if (!s->dpms_supported_p) - gtk_frame_set_label (GTK_FRAME (win->dpms_frame), - _("Display Power Management (not supported by this display)")); + { + gtk_frame_set_label (GTK_FRAME (win->dpms_frame), + (s->dpms_why ? s->dpms_why : + _("Display Power Management (not supported by this display)"))); + } + else if (s->dpms_partial_p) + { + const char *s1 = _("Wayland doesn't implement \"Standby\""); + const char *s2 = _("Wayland doesn't implement \"Suspend\""); + gtk_widget_set_tooltip_text (win->dpms_standby_label, s1); + gtk_widget_set_tooltip_text (win->dpms_standby_mlabel, s1); + gtk_widget_set_tooltip_text (win->dpms_standby_spinbutton, s1); + gtk_widget_set_tooltip_text (win->dpms_suspend_label, s2); + gtk_widget_set_tooltip_text (win->dpms_suspend_mlabel, s2); + gtk_widget_set_tooltip_text (win->dpms_suspend_spinbutton, s2); + } + + if (!s->grabbing_supported_p && s->grab_why) + { + gtk_widget_set_tooltip_text (win->fade_button, s->grab_why); + gtk_widget_set_tooltip_text (win->unfade_button, s->grab_why); + gtk_widget_set_tooltip_text (win->fade_label, s->grab_why); + gtk_widget_set_tooltip_text (win->fade_spinbutton, s->grab_why); + gtk_widget_set_tooltip_text (win->grab_desk_button, s->grab_why); + } } @@ -2937,7 +2976,8 @@ sensitize_menu_items (state *s, Bool force_p) } gtk_widget_set_sensitive (win->activate_menuitem, running_p); - gtk_widget_set_sensitive (win->lock_menuitem, running_p); + gtk_widget_set_sensitive (win->lock_menuitem, (running_p && + s->locking_supported_p)); gtk_widget_set_sensitive (win->kill_menuitem, running_p); gtk_menu_item_set_label (GTK_MENU_ITEM (win->restart_menuitem), @@ -4303,9 +4343,9 @@ the_network_is_not_the_computer (gpointer data) /* If we are in a state where the daemon won't work properly, pop up a dialog box explaining why. */ - if (s->wayland_idle) + if (s->have_wayland_idle_p) ; /* Connected to Wayland and can detect activity. */ - else if (s->wayland_dpy) + else if (s->have_wayland_p) { /* Connected but the necessary extensions are missing. */ warning_dialog (s->window, _("Warning"), @@ -5045,11 +5085,17 @@ const gchar *accels[][2] = { static void xscreensaver_window_realize (GtkWidget *self, gpointer user_data) { - GdkDisplay *gdpy = gdk_display_get_default(); XScreenSaverWindow *win = XSCREENSAVER_WINDOW (self); + GdkDisplay *gdpy = gdk_display_get_default(); state *s = &win->state; saver_preferences *p = &s->prefs; +# ifdef HAVE_WAYLAND + wayland_dpy *wayland_dpy; + wayland_idle *wayland_idle; + wayland_dpms *wayland_dpms; +# endif + s->initializing_p = TRUE; s->short_version = XSCREENSAVER_VERSION; s->window = GTK_WINDOW (win); @@ -5142,9 +5188,9 @@ xscreensaver_window_realize (GtkWidget *self, gpointer user_data) /* Connect to the Wayland server in the same way that xscreensaver and xscreensaver-gfx will, to see if blanking and DPMS will work. */ - s->wayland_dpy = wayland_dpy_connect(); - s->wayland_idle = wayland_idle_init (s->wayland_dpy, NULL, NULL); - s->wayland_dpms = wayland_dpms_init (s->wayland_dpy); + wayland_dpy = wayland_dpy_connect(); + wayland_idle = wayland_idle_init (wayland_dpy, NULL, NULL); + wayland_dpms = wayland_dpms_init (wayland_dpy); # endif /* HAVE_WAYLAND */ s->multi_screen_p = multi_screen_p (s->dpy); @@ -5152,17 +5198,26 @@ xscreensaver_window_realize (GtkWidget *self, gpointer user_data) /* Let's see if the server supports DPMS. */ s->dpms_supported_p = FALSE; - s->dpms_partial_p = TRUE; + s->dpms_partial_p = FALSE; # ifdef HAVE_WAYLAND - if (s->wayland_dpms) + if (wayland_dpy) s->have_wayland_p = TRUE; + if (wayland_idle) s->have_wayland_idle_p = TRUE; + + if (wayland_dpms) { s->dpms_supported_p = TRUE; s->dpms_partial_p = TRUE; } - else if (s->wayland_dpy) + else if (wayland_dpy) { + char *desk = getenv ("XDG_CURRENT_DESKTOP"); s->dpms_supported_p = FALSE; + if (desk && strcasestr (desk, "GNOME")) + s->dpms_why = _("Power management not supported by Wayland GNOME"); + else + s->dpms_why = + _("Power management not supported by this Wayland display"); } else # endif /* HAVE_WAYLAND */ @@ -5171,18 +5226,48 @@ xscreensaver_window_realize (GtkWidget *self, gpointer user_data) { int op = 0, event = 0, error = 0; if (s->dpy && XQueryExtension (s->dpy, "DPMS", &op, &event, &error)) - /* Technically this should also check DPMSCapable(), but this is - almost certainly close enough. */ - s->dpms_supported_p = TRUE; - else if (s->debug_p) - fprintf (stderr, "%s: server does not support power management\n", - blurb()); + { + /* Technically this should also check DPMSCapable(), but this is + almost certainly close enough. */ + s->dpms_supported_p = TRUE; + s->dpms_partial_p = FALSE; + } + else + { + s->dpms_why = _("Power management not supported by this X11 display"); + if (s->debug_p) + fprintf (stderr, "%s: %s\n", blurb(), s->dpms_why); + } } # else /* !HAVE_DPMS_EXTENSION */ if (s->debug_p) fprintf (stderr, "%s: DPMS not supported at compile time\n", blurb()); # endif /* !HAVE_DPMS_EXTENSION */ +# ifdef HAVE_WAYLAND + /* Disconnect from Wayland to release the wlr DPMS protocol, since, + stupidly, only one client can connect at a time and the daemon needs it. + It does not release until the Wayland display is fully shut down: merely + doing wayland_dpms_free() is insufficient. + */ + if (wayland_dpms) + { + wayland_dpms_free (wayland_dpms); + wayland_dpms = 0; + } + if (wayland_idle) + { + wayland_idle_free (wayland_idle); + wayland_idle = 0; + } + if (wayland_dpy) + { + wayland_dpy_close (wayland_dpy); + wayland_dpy = 0; + } +# endif /* !HAVE_WAYLAND */ + + # if defined(__APPLE__) && !defined(HAVE_COCOA) && !defined(__OPTIMIZE__) s->dpms_supported_p = TRUE; /* macOS X11: debugging kludge */ # endif @@ -5197,24 +5282,30 @@ xscreensaver_window_realize (GtkWidget *self, gpointer user_data) { const char *prog = "grim"; char *desk = getenv ("XDG_CURRENT_DESKTOP"); - if (desk && - (strcasestr (desk, "GNOME") || - strcasestr (desk, "KDE") || - strcasestr (desk, "plasma"))) + if (desk && strcasestr (desk, "GNOME")) { s->grabbing_supported_p = False; + s->grab_why = + _("Screenshots and fading not supported on Wayland GNOME"); if (s->debug_p) - fprintf (stderr, - "%s: screenshots and fading not supported on Wayland %s\n", - blurb(), desk); + fprintf (stderr, "%s: %s\n", blurb(), s->grab_why); + } + else if (desk && (strcasestr (desk, "KDE") || + strcasestr (desk, "plasma"))) + { + s->grabbing_supported_p = False; + s->grab_why = + _("Screenshots and fading not supported on Wayland KDE"); + if (s->debug_p) + fprintf (stderr, "%s: %s\n", blurb(), s->grab_why); } else if (! on_path_p (prog)) { s->grabbing_supported_p = False; + s->grab_why = + _("Screenshots and fading on Wayland require \"grim\""); if (s->debug_p) - fprintf (stderr, - "%s: screenshots and fading on Wayland require \"%s\"\n", - blurb(), prog); + fprintf (stderr, "%s: %s\n", blurb(), s->grab_why); } } @@ -5231,10 +5322,10 @@ xscreensaver_window_realize (GtkWidget *self, gpointer user_data) gtk_window_set_transient_for (GTK_WINDOW (s->dialog), GTK_WINDOW (win)); - sensitize_menu_items (s, TRUE); populate_hack_list (s); populate_prefs_page (s); sensitize_demo_widgets (s, FALSE); + sensitize_menu_items (s, TRUE); scroll_to_current_hack (s); if (s->dpy && s->backend != WAYLAND_BACKEND) fix_preview_visual (s); diff --git a/driver/test-wayland-lock.c b/driver/test-wayland-lock.c new file mode 100644 index 000000000..d7808d622 --- /dev/null +++ b/driver/test-wayland-lock.c @@ -0,0 +1,160 @@ +/* test-wayland-lock.c --- test harness for ext-session-lock-v1 + * xscreensaver, Copyright © 2025 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include + +#include +#include + +#ifndef HAVE_WAYLAND +# error Wayland is required +#endif + +#include "wayland-dpy.h" +#include "wayland-lock.h" + +#include "xscreensaver.h" +#include "resources.h" +#include "screens.h" +#include "atoms.h" + +XrmDatabase db = 0; +char *progclass = "XScreenSaver"; +Bool debug_p = True; + +typedef struct { + XtAppContext app; + wayland_dpy *wdpy; + wayland_lock *wlock; + int duration; +} wayland_lock_state; + + +static Window +get_window_cb (const char *name, void *closure) +{ + /* wayland_lock_state *state = (wayland_lock_state *) closure; */ + fprintf (stderr, "%s: get_window_cb unimplemented\n", blurb()); + return 0; +} + +static void +reshape_cb (const char *name, unsigned int w, unsigned int h, void *closure) +{ + /* wayland_lock_state *state = (wayland_lock_state *) closure; */ + fprintf (stderr, "%s: reshape_cb unimplemented\n", blurb()); + abort(); +} + +static void +unlocked_cb (void *closure) +{ + /* wayland_lock_state *state = (wayland_lock_state *) closure; */ + fprintf (stderr, "%s: server unlocked us!\n", blurb()); + exit (1); +} + + + +static void +wayland_dpy_cb (XtPointer closure, int *source, XtInputId *id) +{ + wayland_lock_state *state = (wayland_lock_state *) closure; + wayland_dpy_process_events (state->wdpy, False); +} + + +static void +unlock_timer (XtPointer closure, XtIntervalId *id) +{ + wayland_lock_state *state = (wayland_lock_state *) closure; + fprintf (stderr, "%s: unlocking...\n", blurb()); + wayland_unlock_screen (state->wlock); +} + + +static void +lock_timer (XtPointer closure, XtIntervalId *id) +{ + wayland_lock_state *state = (wayland_lock_state *) closure; + + fprintf (stderr, "%s: locking...\n", blurb()); + if (! wayland_lock_screen (state->wlock, + get_window_cb, + reshape_cb, + unlocked_cb, + state->wlock)) + { + fprintf (stderr, "%s: FAILED\n", blurb()); + exit (1); + } + + XtAppAddTimeOut (state->app, 1000 * state->duration, unlock_timer, state); +} + + +int +main (int argc, char **argv) +{ + XtAppContext app; + Widget toplevel_shell = XtAppInitialize (&app, progclass, 0, 0, + &argc, argv, 0, 0, 0); + Display *dpy = XtDisplay (toplevel_shell); + wayland_dpy *wdpy = wayland_dpy_connect(); + wayland_lock *wlock = wayland_lock_init (wdpy); + wayland_lock_state S, *state = &S; + + progname = argv[0]; + progclass = "XScreenSaver"; + db = XtDatabase (dpy); + + if (!wdpy) + { + fprintf (stderr, "%s: wayland: connection failed.\n", blurb()); + exit (1); + } + if (!wlock) + { + fprintf (stderr, "%s: wayland: locking unsupported.\n", blurb()); + exit (1); + } + + verbose_p += 2; + + state->duration = 3; + state->app = app; + state->wdpy = wdpy; + state->wlock = wlock; + + XtAppAddInput (app, wayland_dpy_get_fd (wdpy), + (XtPointer) (XtInputReadMask | XtInputExceptMask), + wayland_dpy_cb, (XtPointer) state); + + XtAppAddTimeOut (app, 1000 * state->duration, lock_timer, state); + + fprintf (stderr, "%s: locking in %d sec...\n", blurb(), state->duration); + while (1) + { + XEvent event; + XtAppNextEvent (app, &event); + XtDispatchEvent (&event); + } +} diff --git a/driver/wayland-dpms.c b/driver/wayland-dpms.c index 536a86b24..61dcdaf16 100644 --- a/driver/wayland-dpms.c +++ b/driver/wayland-dpms.c @@ -23,6 +23,13 @@ * there is user activity. So if this program crashes with the screens off, * good luck getting them to turn back on. KDE does the right thing. * + * Also also! Under "wlr", there can be only one listener at a time! + * That's right, it's vitally important that two different programs be + * unable to interrogate the DPMS state simultaneously! So if someone + * else is already listening to this, we're screwed. Also also also! + * Calling 'destroy' does not release the lock. The lock is held until + * the entire Wayland display connection terminates. Because reasons? + * * GNOME does the following crap, because they have never seen a Wayland * protocol that they didn't think should be replaced with DBus instead: * @@ -78,11 +85,11 @@ typedef struct dpms_output { Bool wl_done; /* wl_output: all info about this output has been sent */ struct zwlr_output_power_v1 *wlr_out; - enum zwlr_output_power_v1_mode wlr_mode; - Bool wlr_failed; /* I have no idea what this means */ + enum zwlr_output_power_v1_mode wlr_mode; /* On, Off */ + Bool wlr_failed; struct org_kde_kwin_dpms *kde_out; - enum org_kde_kwin_dpms_mode kde_mode; + enum org_kde_kwin_dpms_mode kde_mode; /* On, Standby, Suspend, Off */ Bool kde_done; } dpms_output; @@ -154,8 +161,8 @@ wlr_handle_failed (void *data, struct zwlr_output_power_v1 *wlr_output_power) dpms_output *out = (dpms_output *) data; out->wlr_failed = True; if (verbose_p > 2) - fprintf (stderr, "%s: wayland: dpms: output %s is FAILED?\n", blurb(), - out->name); + fprintf (stderr, "%s: wayland: dpms: output %s is in FAILED state\n", + blurb(), out->name); } @@ -218,6 +225,8 @@ handle_global (void *data, struct wl_registry *reg, }; dpms_output *out = (dpms_output *) calloc (sizeof (*out), 1); + out->wlr_mode = ZWLR_OUTPUT_POWER_V1_MODE_ON; + out->kde_mode = ORG_KDE_KWIN_DPMS_MODE_ON; wl_list_insert (&state->outputs, &out->link); if (verbose_p > 2) @@ -327,13 +336,22 @@ wayland_dpms_free (wayland_dpms *state) wl_list_for_each_safe (out, tmp, &state->outputs, link) { wl_list_remove (&out->link); - /* #### out->wl_output ? */ - /* #### out->zwlr_output_power_v1, etc ? */ + if (out->wlr_out) + zwlr_output_power_v1_destroy (out->wlr_out); + if (out->kde_out) + org_kde_kwin_dpms_destroy (out->kde_out); + if (out->wl_output) + wl_output_destroy (out->wl_output); free (out); } - /* #### state->reg ? */ - /* #### state->zwlr_output_power_manager_v1, etc ? */ + if (state->wlr_mgr) + zwlr_output_power_manager_v1_destroy (state->wlr_mgr); + if (state->kde_mgr) + org_kde_kwin_dpms_manager_destroy (state->kde_mgr); + if (state->reg) + wl_proxy_destroy ((struct wl_proxy *) state->reg); + free (state); } @@ -343,29 +361,43 @@ wayland_dpms_free (wayland_dpms *state) Bool wayland_monitor_powered_on_p (wayland_dpms *state) { - Bool on_p = False; + Bool off_p = False; + Bool failed_p = False; dpms_output *out; - if (!state) return on_p; + if (!state) return !off_p; wayland_dpy_process_events (state->parent, True); wl_list_for_each (out, &state->outputs, link) { if (out->wlr_out) { - if (out->wlr_mode == ZWLR_OUTPUT_POWER_V1_MODE_ON) - on_p = True; + if (out->wlr_mode != ZWLR_OUTPUT_POWER_V1_MODE_ON) + off_p = True; + if (out->wlr_failed) + failed_p = True; } else if (out->kde_out) { - if (out->kde_mode == ORG_KDE_KWIN_DPMS_MODE_ON) - on_p = True; + if (out->kde_mode != ORG_KDE_KWIN_DPMS_MODE_ON) + off_p = True; } else abort(); } - return on_p; + if (failed_p) + { + /* if (verbose_p) */ + fprintf (stderr, "%s: wayland: dpms: outputs entered 'failed' state\n", + blurb()); + /* If the outputs are in 'failed' state, assume they are on. If there + was another listener to "wlr", we will always get "failed", because + there can be only one listener. */ + off_p = False; + } + + return !off_p; } diff --git a/driver/wayland-dpy.c b/driver/wayland-dpy.c index db5c922ec..fdf760477 100644 --- a/driver/wayland-dpy.c +++ b/driver/wayland-dpy.c @@ -83,7 +83,6 @@ wayland_dpy_connect (void) wl_display_get_fd (state->dpy), WL_EVENT_READABLE, handle_event, state); wl_event_source_check (source); - /* #### Do I need to free 'source'? */ } wayland_dpy_process_events (state, 0); @@ -133,6 +132,7 @@ wayland_dpy_process_events (wayland_dpy *state, int sync_p) void wayland_dpy_close (wayland_dpy *state) { + wayland_dpy_process_events (state, 0); wl_display_disconnect (state->dpy); if (state->event_loop) wl_event_loop_destroy (state->event_loop); diff --git a/driver/wayland-dpy.h b/driver/wayland-dpy.h index 585dce072..9f9cf4eaf 100644 --- a/driver/wayland-dpy.h +++ b/driver/wayland-dpy.h @@ -15,6 +15,7 @@ typedef struct wayland_dpy wayland_dpy; typedef struct wayland_idle wayland_idle; typedef struct wayland_dpms wayland_dpms; +typedef struct wayland_lock wayland_lock; /* Connects to Wayland and returns a state object on success. */ extern wayland_dpy *wayland_dpy_connect (void); diff --git a/driver/wayland-idle.c b/driver/wayland-idle.c index 734e35ebc..9c503da7c 100644 --- a/driver/wayland-idle.c +++ b/driver/wayland-idle.c @@ -42,14 +42,11 @@ struct wayland_idle { struct wl_display *dpy; struct wl_registry *reg; struct wl_event_loop *event_loop; + struct wl_seat *seat; void (*activity_cb) (void *closure); void *closure; - struct wl_seat *seat; - char *seat_name; - uint32_t seat_caps; - struct ext_idle_notifier_v1 *ext_idle_notifier; struct ext_idle_notification_v1 *ext_idle_notification; @@ -58,26 +55,6 @@ struct wayland_idle { }; -static void -seat_handle_capabilities (void *data, struct wl_seat *seat, uint32_t caps) -{ - wayland_idle *state = (wayland_idle *) data; - state->seat_caps = caps; - if (verbose_p > 2) - fprintf (stderr, "%s: wayland: idle: seat caps: 0x%02lX\n", blurb(), - (unsigned long) caps); -} - -static void -seat_handle_name (void *data, struct wl_seat *seat, const char *name) -{ - wayland_idle *state = (wayland_idle *) data; - state->seat_name = strdup (name); - if (verbose_p > 2) - fprintf (stderr, "%s: wayland: idle: seat name: \"%s\"\n", blurb(), name); -} - - /* This is an iterator for all of the extensions that Wayland provides, so we can find the ones we are interested in. */ @@ -89,14 +66,9 @@ handle_global (void *data, struct wl_registry *reg, if (!strcmp (iface, wl_seat_interface.name)) { - static const struct wl_seat_listener seat_listener = { - .name = seat_handle_name, - .capabilities = seat_handle_capabilities, - }; if (verbose_p > 2) fprintf (stderr, "%s: wayland: idle: found: %s\n", blurb(), iface); state->seat = wl_registry_bind (reg, name, &wl_seat_interface, version); - wl_seat_add_listener (state->seat, &seat_listener, state); } else if (!strcmp (iface, ext_idle_notifier_v1_interface.name)) { @@ -250,7 +222,6 @@ wayland_idle_init (wayland_dpy *dpy, state->reg = wl_display_get_registry (dpy->dpy); wl_registry_add_listener (state->reg, &listener, state); - /* It takes two round trips: first to register seats, then timers. */ wayland_dpy_process_events (dpy, true); if (! state->seat) @@ -280,10 +251,14 @@ wayland_idle_init (wayland_dpy *dpy, void wayland_idle_free (wayland_idle *state) { - if (state->seat_name) - free (state->seat_name); - /* #### state->reg ? */ - /* #### state->seat ? */ - /* #### state->ext_idle_notifier, etc ? */ + if (state->seat) + wl_seat_destroy (state->seat); + if (state->ext_idle_notifier) + ext_idle_notifier_v1_destroy (state->ext_idle_notifier); + if (state->ext_idle_notification) + ext_idle_notification_v1_destroy (state->ext_idle_notification); + if (state->reg) + wl_proxy_destroy ((struct wl_proxy *) state->reg); + free (state); } diff --git a/driver/wayland-lock.h b/driver/wayland-lock.h new file mode 100644 index 000000000..9ddb00d60 --- /dev/null +++ b/driver/wayland-lock.h @@ -0,0 +1,41 @@ +/* xscreensaver, Copyright © 2025 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. + */ + +#ifndef __XSCREENSAVER_WAYLAND_LOCK_H__ +#define __XSCREENSAVER_WAYLAND_LOCK_H__ + +/* Binds to Wayland locking protocols and returns an opaque state object + on success. + */ +extern wayland_lock *wayland_lock_init (wayland_dpy *); + +/* Locks the screen. Returns true on success. + + The 'get_window' callback must return an X11 Window corresponding to the + wl_output with the given name (RANDR screen). + + The 'unlocked' callback is run if the server forcibly unlocks us. + */ +extern Bool +wayland_lock_screen (wayland_lock *, + Window (*get_window_cb) (const char *name, void *closure), + void (*reshape_cb) (const char *name, + unsigned int w, unsigned int h, + void *closure), + void (*unlocked_cb) (void *closure), + void *closure); + +extern void wayland_unlock_screen (wayland_lock *); + +/* Shut it all down. If the screen is locked it may remain locked. */ +extern void wayland_lock_free (wayland_lock *); + +#endif /* __XSCREENSAVER_WAYLAND_LOCK_H__ */ diff --git a/driver/wayland-protocols/ext-session-lock-v1-client-protocol.h b/driver/wayland-protocols/ext-session-lock-v1-client-protocol.h new file mode 100644 index 000000000..994977a22 --- /dev/null +++ b/driver/wayland-protocols/ext-session-lock-v1-client-protocol.h @@ -0,0 +1,684 @@ +/* Generated by wayland-scanner 1.23.1 */ + +#ifndef EXT_SESSION_LOCK_V1_CLIENT_PROTOCOL_H +#define EXT_SESSION_LOCK_V1_CLIENT_PROTOCOL_H + +#include +#include +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_ext_session_lock_v1 The ext_session_lock_v1 protocol + * secure session locking with arbitrary graphics + * + * @section page_desc_ext_session_lock_v1 Description + * + * This protocol allows for a privileged Wayland client to lock the session + * and display arbitrary graphics while the session is locked. + * + * The compositor may choose to restrict this protocol to a special client + * launched by the compositor itself or expose it to all privileged clients, + * this is compositor policy. + * + * The client is responsible for performing authentication and informing the + * compositor when the session should be unlocked. If the client dies while + * the session is locked the session remains locked, possibly permanently + * depending on compositor policy. + * + * The key words "must", "must not", "required", "shall", "shall not", + * "should", "should not", "recommended", "may", and "optional" in this + * document are to be interpreted as described in IETF RFC 2119. + * + * Warning! The protocol described in this file is currently in the + * testing phase. Backward compatible changes may be added together with + * the corresponding interface version bump. Backward incompatible changes + * can only be done by creating a new major version of the extension. + * + * @section page_ifaces_ext_session_lock_v1 Interfaces + * - @subpage page_iface_ext_session_lock_manager_v1 - used to lock the session + * - @subpage page_iface_ext_session_lock_v1 - manage lock state and create lock surfaces + * - @subpage page_iface_ext_session_lock_surface_v1 - a surface displayed while the session is locked + * @section page_copyright_ext_session_lock_v1 Copyright + *
+ *
+ * Copyright 2021 Isaac Freund
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ * 
+ */ +struct ext_session_lock_manager_v1; +struct ext_session_lock_surface_v1; +struct ext_session_lock_v1; +struct wl_output; +struct wl_surface; + +#ifndef EXT_SESSION_LOCK_MANAGER_V1_INTERFACE +#define EXT_SESSION_LOCK_MANAGER_V1_INTERFACE +/** + * @page page_iface_ext_session_lock_manager_v1 ext_session_lock_manager_v1 + * @section page_iface_ext_session_lock_manager_v1_desc Description + * + * This interface is used to request that the session be locked. + * @section page_iface_ext_session_lock_manager_v1_api API + * See @ref iface_ext_session_lock_manager_v1. + */ +/** + * @defgroup iface_ext_session_lock_manager_v1 The ext_session_lock_manager_v1 interface + * + * This interface is used to request that the session be locked. + */ +extern const struct wl_interface ext_session_lock_manager_v1_interface; +#endif +#ifndef EXT_SESSION_LOCK_V1_INTERFACE +#define EXT_SESSION_LOCK_V1_INTERFACE +/** + * @page page_iface_ext_session_lock_v1 ext_session_lock_v1 + * @section page_iface_ext_session_lock_v1_desc Description + * + * In response to the creation of this object the compositor must send + * either the locked or finished event. + * + * The locked event indicates that the session is locked. This means + * that the compositor must stop rendering and providing input to normal + * clients. Instead the compositor must blank all outputs with an opaque + * color such that their normal content is fully hidden. + * + * The only surfaces that should be rendered while the session is locked + * are the lock surfaces created through this interface and optionally, + * at the compositor's discretion, special privileged surfaces such as + * input methods or portions of desktop shell UIs. + * + * The locked event must not be sent until a new "locked" frame (either + * from a session lock surface or the compositor blanking the output) has + * been presented on all outputs and no security sensitive normal/unlocked + * content is possibly visible. + * + * The finished event should be sent immediately on creation of this + * object if the compositor decides that the locked event will not be sent. + * + * The compositor may wait for the client to create and render session lock + * surfaces before sending the locked event to avoid displaying intermediate + * blank frames. However, it must impose a reasonable time limit if + * waiting and send the locked event as soon as the hard requirements + * described above can be met if the time limit expires. Clients should + * immediately create lock surfaces for all outputs on creation of this + * object to make this possible. + * + * This behavior of the locked event is required in order to prevent + * possible race conditions with clients that wish to suspend the system + * or similar after locking the session. Without these semantics, clients + * triggering a suspend after receiving the locked event would race with + * the first "locked" frame being presented and normal/unlocked frames + * might be briefly visible as the system is resumed if the suspend + * operation wins the race. + * + * If the client dies while the session is locked, the compositor must not + * unlock the session in response. It is acceptable for the session to be + * permanently locked if this happens. The compositor may choose to continue + * to display the lock surfaces the client had mapped before it died or + * alternatively fall back to a solid color, this is compositor policy. + * + * Compositors may also allow a secure way to recover the session, the + * details of this are compositor policy. Compositors may allow a new + * client to create a ext_session_lock_v1 object and take responsibility + * for unlocking the session, they may even start a new lock client + * instance automatically. + * @section page_iface_ext_session_lock_v1_api API + * See @ref iface_ext_session_lock_v1. + */ +/** + * @defgroup iface_ext_session_lock_v1 The ext_session_lock_v1 interface + * + * In response to the creation of this object the compositor must send + * either the locked or finished event. + * + * The locked event indicates that the session is locked. This means + * that the compositor must stop rendering and providing input to normal + * clients. Instead the compositor must blank all outputs with an opaque + * color such that their normal content is fully hidden. + * + * The only surfaces that should be rendered while the session is locked + * are the lock surfaces created through this interface and optionally, + * at the compositor's discretion, special privileged surfaces such as + * input methods or portions of desktop shell UIs. + * + * The locked event must not be sent until a new "locked" frame (either + * from a session lock surface or the compositor blanking the output) has + * been presented on all outputs and no security sensitive normal/unlocked + * content is possibly visible. + * + * The finished event should be sent immediately on creation of this + * object if the compositor decides that the locked event will not be sent. + * + * The compositor may wait for the client to create and render session lock + * surfaces before sending the locked event to avoid displaying intermediate + * blank frames. However, it must impose a reasonable time limit if + * waiting and send the locked event as soon as the hard requirements + * described above can be met if the time limit expires. Clients should + * immediately create lock surfaces for all outputs on creation of this + * object to make this possible. + * + * This behavior of the locked event is required in order to prevent + * possible race conditions with clients that wish to suspend the system + * or similar after locking the session. Without these semantics, clients + * triggering a suspend after receiving the locked event would race with + * the first "locked" frame being presented and normal/unlocked frames + * might be briefly visible as the system is resumed if the suspend + * operation wins the race. + * + * If the client dies while the session is locked, the compositor must not + * unlock the session in response. It is acceptable for the session to be + * permanently locked if this happens. The compositor may choose to continue + * to display the lock surfaces the client had mapped before it died or + * alternatively fall back to a solid color, this is compositor policy. + * + * Compositors may also allow a secure way to recover the session, the + * details of this are compositor policy. Compositors may allow a new + * client to create a ext_session_lock_v1 object and take responsibility + * for unlocking the session, they may even start a new lock client + * instance automatically. + */ +extern const struct wl_interface ext_session_lock_v1_interface; +#endif +#ifndef EXT_SESSION_LOCK_SURFACE_V1_INTERFACE +#define EXT_SESSION_LOCK_SURFACE_V1_INTERFACE +/** + * @page page_iface_ext_session_lock_surface_v1 ext_session_lock_surface_v1 + * @section page_iface_ext_session_lock_surface_v1_desc Description + * + * The client may use lock surfaces to display a screensaver, render a + * dialog to enter a password and unlock the session, or however else it + * sees fit. + * + * On binding this interface the compositor will immediately send the + * first configure event. After making the ack_configure request in + * response to this event the client should attach and commit the first + * buffer. Committing the surface before acking the first configure is a + * protocol error. Committing the surface with a null buffer at any time + * is a protocol error. + * + * The compositor is free to handle keyboard/pointer focus for lock + * surfaces however it chooses. A reasonable way to do this would be to + * give the first lock surface created keyboard focus and change keyboard + * focus if the user clicks on other surfaces. + * @section page_iface_ext_session_lock_surface_v1_api API + * See @ref iface_ext_session_lock_surface_v1. + */ +/** + * @defgroup iface_ext_session_lock_surface_v1 The ext_session_lock_surface_v1 interface + * + * The client may use lock surfaces to display a screensaver, render a + * dialog to enter a password and unlock the session, or however else it + * sees fit. + * + * On binding this interface the compositor will immediately send the + * first configure event. After making the ack_configure request in + * response to this event the client should attach and commit the first + * buffer. Committing the surface before acking the first configure is a + * protocol error. Committing the surface with a null buffer at any time + * is a protocol error. + * + * The compositor is free to handle keyboard/pointer focus for lock + * surfaces however it chooses. A reasonable way to do this would be to + * give the first lock surface created keyboard focus and change keyboard + * focus if the user clicks on other surfaces. + */ +extern const struct wl_interface ext_session_lock_surface_v1_interface; +#endif + +#define EXT_SESSION_LOCK_MANAGER_V1_DESTROY 0 +#define EXT_SESSION_LOCK_MANAGER_V1_LOCK 1 + + +/** + * @ingroup iface_ext_session_lock_manager_v1 + */ +#define EXT_SESSION_LOCK_MANAGER_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_ext_session_lock_manager_v1 + */ +#define EXT_SESSION_LOCK_MANAGER_V1_LOCK_SINCE_VERSION 1 + +/** @ingroup iface_ext_session_lock_manager_v1 */ +static inline void +ext_session_lock_manager_v1_set_user_data(struct ext_session_lock_manager_v1 *ext_session_lock_manager_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) ext_session_lock_manager_v1, user_data); +} + +/** @ingroup iface_ext_session_lock_manager_v1 */ +static inline void * +ext_session_lock_manager_v1_get_user_data(struct ext_session_lock_manager_v1 *ext_session_lock_manager_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) ext_session_lock_manager_v1); +} + +static inline uint32_t +ext_session_lock_manager_v1_get_version(struct ext_session_lock_manager_v1 *ext_session_lock_manager_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) ext_session_lock_manager_v1); +} + +/** + * @ingroup iface_ext_session_lock_manager_v1 + * + * This informs the compositor that the session lock manager object will + * no longer be used. Existing objects created through this interface + * remain valid. + */ +static inline void +ext_session_lock_manager_v1_destroy(struct ext_session_lock_manager_v1 *ext_session_lock_manager_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) ext_session_lock_manager_v1, + EXT_SESSION_LOCK_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) ext_session_lock_manager_v1), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_ext_session_lock_manager_v1 + * + * This request creates a session lock and asks the compositor to lock the + * session. The compositor will send either the ext_session_lock_v1.locked + * or ext_session_lock_v1.finished event on the created object in + * response to this request. + */ +static inline struct ext_session_lock_v1 * +ext_session_lock_manager_v1_lock(struct ext_session_lock_manager_v1 *ext_session_lock_manager_v1) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_flags((struct wl_proxy *) ext_session_lock_manager_v1, + EXT_SESSION_LOCK_MANAGER_V1_LOCK, &ext_session_lock_v1_interface, wl_proxy_get_version((struct wl_proxy *) ext_session_lock_manager_v1), 0, NULL); + + return (struct ext_session_lock_v1 *) id; +} + +#ifndef EXT_SESSION_LOCK_V1_ERROR_ENUM +#define EXT_SESSION_LOCK_V1_ERROR_ENUM +enum ext_session_lock_v1_error { + /** + * attempted to destroy session lock while locked + */ + EXT_SESSION_LOCK_V1_ERROR_INVALID_DESTROY = 0, + /** + * unlock requested but locked event was never sent + */ + EXT_SESSION_LOCK_V1_ERROR_INVALID_UNLOCK = 1, + /** + * given wl_surface already has a role + */ + EXT_SESSION_LOCK_V1_ERROR_ROLE = 2, + /** + * given output already has a lock surface + */ + EXT_SESSION_LOCK_V1_ERROR_DUPLICATE_OUTPUT = 3, + /** + * given wl_surface has a buffer attached or committed + */ + EXT_SESSION_LOCK_V1_ERROR_ALREADY_CONSTRUCTED = 4, +}; +#endif /* EXT_SESSION_LOCK_V1_ERROR_ENUM */ + +/** + * @ingroup iface_ext_session_lock_v1 + * @struct ext_session_lock_v1_listener + */ +struct ext_session_lock_v1_listener { + /** + * session successfully locked + * + * This client is now responsible for displaying graphics while + * the session is locked and deciding when to unlock the session. + * + * The locked event must not be sent until a new "locked" frame has + * been presented on all outputs and no security sensitive + * normal/unlocked content is possibly visible. + * + * If this event is sent, making the destroy request is a protocol + * error, the lock object must be destroyed using the + * unlock_and_destroy request. + */ + void (*locked)(void *data, + struct ext_session_lock_v1 *ext_session_lock_v1); + /** + * the session lock object should be destroyed + * + * The compositor has decided that the session lock should be + * destroyed as it will no longer be used by the compositor. + * Exactly when this event is sent is compositor policy, but it + * must never be sent more than once for a given session lock + * object. + * + * This might be sent because there is already another + * ext_session_lock_v1 object held by a client, or the compositor + * has decided to deny the request to lock the session for some + * other reason. This might also be sent because the compositor + * implements some alternative, secure way to authenticate and + * unlock the session. + * + * The finished event should be sent immediately on creation of + * this object if the compositor decides that the locked event will + * not be sent. + * + * If the locked event is sent on creation of this object the + * finished event may still be sent at some later time in this + * object's lifetime. This is compositor policy. + * + * Upon receiving this event, the client should make either the + * destroy request or the unlock_and_destroy request, depending on + * whether or not the locked event was received on this object. + */ + void (*finished)(void *data, + struct ext_session_lock_v1 *ext_session_lock_v1); +}; + +/** + * @ingroup iface_ext_session_lock_v1 + */ +static inline int +ext_session_lock_v1_add_listener(struct ext_session_lock_v1 *ext_session_lock_v1, + const struct ext_session_lock_v1_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) ext_session_lock_v1, + (void (**)(void)) listener, data); +} + +#define EXT_SESSION_LOCK_V1_DESTROY 0 +#define EXT_SESSION_LOCK_V1_GET_LOCK_SURFACE 1 +#define EXT_SESSION_LOCK_V1_UNLOCK_AND_DESTROY 2 + +/** + * @ingroup iface_ext_session_lock_v1 + */ +#define EXT_SESSION_LOCK_V1_LOCKED_SINCE_VERSION 1 +/** + * @ingroup iface_ext_session_lock_v1 + */ +#define EXT_SESSION_LOCK_V1_FINISHED_SINCE_VERSION 1 + +/** + * @ingroup iface_ext_session_lock_v1 + */ +#define EXT_SESSION_LOCK_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_ext_session_lock_v1 + */ +#define EXT_SESSION_LOCK_V1_GET_LOCK_SURFACE_SINCE_VERSION 1 +/** + * @ingroup iface_ext_session_lock_v1 + */ +#define EXT_SESSION_LOCK_V1_UNLOCK_AND_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_ext_session_lock_v1 */ +static inline void +ext_session_lock_v1_set_user_data(struct ext_session_lock_v1 *ext_session_lock_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) ext_session_lock_v1, user_data); +} + +/** @ingroup iface_ext_session_lock_v1 */ +static inline void * +ext_session_lock_v1_get_user_data(struct ext_session_lock_v1 *ext_session_lock_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) ext_session_lock_v1); +} + +static inline uint32_t +ext_session_lock_v1_get_version(struct ext_session_lock_v1 *ext_session_lock_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) ext_session_lock_v1); +} + +/** + * @ingroup iface_ext_session_lock_v1 + * + * This informs the compositor that the lock object will no longer be + * used. Existing objects created through this interface remain valid. + * + * After this request is made, lock surfaces created through this object + * should be destroyed by the client as they will no longer be used by + * the compositor. + * + * It is a protocol error to make this request if the locked event was + * sent, the unlock_and_destroy request must be used instead. + */ +static inline void +ext_session_lock_v1_destroy(struct ext_session_lock_v1 *ext_session_lock_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) ext_session_lock_v1, + EXT_SESSION_LOCK_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) ext_session_lock_v1), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_ext_session_lock_v1 + * + * The client is expected to create lock surfaces for all outputs + * currently present and any new outputs as they are advertised. These + * won't be displayed by the compositor unless the lock is successful + * and the locked event is sent. + * + * Providing a wl_surface which already has a role or already has a buffer + * attached or committed is a protocol error, as is attaching/committing + * a buffer before the first ext_session_lock_surface_v1.configure event. + * + * Attempting to create more than one lock surface for a given output + * is a duplicate_output protocol error. + */ +static inline struct ext_session_lock_surface_v1 * +ext_session_lock_v1_get_lock_surface(struct ext_session_lock_v1 *ext_session_lock_v1, struct wl_surface *surface, struct wl_output *output) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_flags((struct wl_proxy *) ext_session_lock_v1, + EXT_SESSION_LOCK_V1_GET_LOCK_SURFACE, &ext_session_lock_surface_v1_interface, wl_proxy_get_version((struct wl_proxy *) ext_session_lock_v1), 0, NULL, surface, output); + + return (struct ext_session_lock_surface_v1 *) id; +} + +/** + * @ingroup iface_ext_session_lock_v1 + * + * This request indicates that the session should be unlocked, for + * example because the user has entered their password and it has been + * verified by the client. + * + * This request also informs the compositor that the lock object will + * no longer be used and should be destroyed. Existing objects created + * through this interface remain valid. + * + * After this request is made, lock surfaces created through this object + * should be destroyed by the client as they will no longer be used by + * the compositor. + * + * It is a protocol error to make this request if the locked event has + * not been sent. In that case, the lock object must be destroyed using + * the destroy request. + * + * Note that a correct client that wishes to exit directly after unlocking + * the session must use the wl_display.sync request to ensure the server + * receives and processes the unlock_and_destroy request. Otherwise + * there is no guarantee that the server has unlocked the session due + * to the asynchronous nature of the Wayland protocol. For example, + * the server might terminate the client with a protocol error before + * it processes the unlock_and_destroy request. + */ +static inline void +ext_session_lock_v1_unlock_and_destroy(struct ext_session_lock_v1 *ext_session_lock_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) ext_session_lock_v1, + EXT_SESSION_LOCK_V1_UNLOCK_AND_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) ext_session_lock_v1), WL_MARSHAL_FLAG_DESTROY); +} + +#ifndef EXT_SESSION_LOCK_SURFACE_V1_ERROR_ENUM +#define EXT_SESSION_LOCK_SURFACE_V1_ERROR_ENUM +enum ext_session_lock_surface_v1_error { + /** + * surface committed before first ack_configure request + */ + EXT_SESSION_LOCK_SURFACE_V1_ERROR_COMMIT_BEFORE_FIRST_ACK = 0, + /** + * surface committed with a null buffer + */ + EXT_SESSION_LOCK_SURFACE_V1_ERROR_NULL_BUFFER = 1, + /** + * failed to match ack'd width/height + */ + EXT_SESSION_LOCK_SURFACE_V1_ERROR_DIMENSIONS_MISMATCH = 2, + /** + * serial provided in ack_configure is invalid + */ + EXT_SESSION_LOCK_SURFACE_V1_ERROR_INVALID_SERIAL = 3, +}; +#endif /* EXT_SESSION_LOCK_SURFACE_V1_ERROR_ENUM */ + +/** + * @ingroup iface_ext_session_lock_surface_v1 + * @struct ext_session_lock_surface_v1_listener + */ +struct ext_session_lock_surface_v1_listener { + /** + * the client should resize its surface + * + * This event is sent once on binding the interface and may be + * sent again at the compositor's discretion, for example if output + * geometry changes. + * + * The width and height are in surface-local coordinates and are + * exact requirements. Failing to match these surface dimensions in + * the next commit after acking a configure is a protocol error. + * @param serial serial for use in ack_configure + */ + void (*configure)(void *data, + struct ext_session_lock_surface_v1 *ext_session_lock_surface_v1, + uint32_t serial, + uint32_t width, + uint32_t height); +}; + +/** + * @ingroup iface_ext_session_lock_surface_v1 + */ +static inline int +ext_session_lock_surface_v1_add_listener(struct ext_session_lock_surface_v1 *ext_session_lock_surface_v1, + const struct ext_session_lock_surface_v1_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) ext_session_lock_surface_v1, + (void (**)(void)) listener, data); +} + +#define EXT_SESSION_LOCK_SURFACE_V1_DESTROY 0 +#define EXT_SESSION_LOCK_SURFACE_V1_ACK_CONFIGURE 1 + +/** + * @ingroup iface_ext_session_lock_surface_v1 + */ +#define EXT_SESSION_LOCK_SURFACE_V1_CONFIGURE_SINCE_VERSION 1 + +/** + * @ingroup iface_ext_session_lock_surface_v1 + */ +#define EXT_SESSION_LOCK_SURFACE_V1_DESTROY_SINCE_VERSION 1 +/** + * @ingroup iface_ext_session_lock_surface_v1 + */ +#define EXT_SESSION_LOCK_SURFACE_V1_ACK_CONFIGURE_SINCE_VERSION 1 + +/** @ingroup iface_ext_session_lock_surface_v1 */ +static inline void +ext_session_lock_surface_v1_set_user_data(struct ext_session_lock_surface_v1 *ext_session_lock_surface_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) ext_session_lock_surface_v1, user_data); +} + +/** @ingroup iface_ext_session_lock_surface_v1 */ +static inline void * +ext_session_lock_surface_v1_get_user_data(struct ext_session_lock_surface_v1 *ext_session_lock_surface_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) ext_session_lock_surface_v1); +} + +static inline uint32_t +ext_session_lock_surface_v1_get_version(struct ext_session_lock_surface_v1 *ext_session_lock_surface_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) ext_session_lock_surface_v1); +} + +/** + * @ingroup iface_ext_session_lock_surface_v1 + * + * This informs the compositor that the lock surface object will no + * longer be used. + * + * It is recommended for a lock client to destroy lock surfaces if + * their corresponding wl_output global is removed. + * + * If a lock surface on an active output is destroyed before the + * ext_session_lock_v1.unlock_and_destroy event is sent, the compositor + * must fall back to rendering a solid color. + */ +static inline void +ext_session_lock_surface_v1_destroy(struct ext_session_lock_surface_v1 *ext_session_lock_surface_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) ext_session_lock_surface_v1, + EXT_SESSION_LOCK_SURFACE_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) ext_session_lock_surface_v1), WL_MARSHAL_FLAG_DESTROY); +} + +/** + * @ingroup iface_ext_session_lock_surface_v1 + * + * When a configure event is received, if a client commits the surface + * in response to the configure event, then the client must make an + * ack_configure request sometime before the commit request, passing + * along the serial of the configure event. + * + * If the client receives multiple configure events before it can + * respond to one, it only has to ack the last configure event. + * + * A client is not required to commit immediately after sending an + * ack_configure request - it may even ack_configure several times + * before its next surface commit. + * + * A client may send multiple ack_configure requests before committing, + * but only the last request sent before a commit indicates which + * configure event the client really is responding to. + * + * Sending an ack_configure request consumes the configure event + * referenced by the given serial, as well as all older configure events + * sent on this object. + * + * It is a protocol error to issue multiple ack_configure requests + * referencing the same configure event or to issue an ack_configure + * request referencing a configure event older than the last configure + * event acked for a given lock surface. + */ +static inline void +ext_session_lock_surface_v1_ack_configure(struct ext_session_lock_surface_v1 *ext_session_lock_surface_v1, uint32_t serial) +{ + wl_proxy_marshal_flags((struct wl_proxy *) ext_session_lock_surface_v1, + EXT_SESSION_LOCK_SURFACE_V1_ACK_CONFIGURE, NULL, wl_proxy_get_version((struct wl_proxy *) ext_session_lock_surface_v1), 0, serial); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/driver/wayland-protocols/ext-session-lock-v1-protocol.c b/driver/wayland-protocols/ext-session-lock-v1-protocol.c new file mode 100644 index 000000000..b5f80c1b6 --- /dev/null +++ b/driver/wayland-protocols/ext-session-lock-v1-protocol.c @@ -0,0 +1,97 @@ +/* Generated by wayland-scanner 1.23.1 */ + +/* + * Copyright 2021 Isaac Freund + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include "wayland-util.h" + +#ifndef __has_attribute +# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ +#endif + +#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) +#define WL_PRIVATE __attribute__ ((visibility("hidden"))) +#else +#define WL_PRIVATE +#endif + +extern const struct wl_interface ext_session_lock_surface_v1_interface; +extern const struct wl_interface ext_session_lock_v1_interface; +extern const struct wl_interface wl_output_interface; +extern const struct wl_interface wl_surface_interface; + +static const struct wl_interface *ext_session_lock_v1_types[] = { + NULL, + NULL, + NULL, + &ext_session_lock_v1_interface, + &ext_session_lock_surface_v1_interface, + &wl_surface_interface, + &wl_output_interface, +}; + +static const struct wl_message ext_session_lock_manager_v1_requests[] = { + { "destroy", "", ext_session_lock_v1_types + 0 }, + { "lock", "n", ext_session_lock_v1_types + 3 }, +}; + +WL_PRIVATE const struct wl_interface ext_session_lock_manager_v1_interface = { + "ext_session_lock_manager_v1", 1, + 2, ext_session_lock_manager_v1_requests, + 0, NULL, +}; + +static const struct wl_message ext_session_lock_v1_requests[] = { + { "destroy", "", ext_session_lock_v1_types + 0 }, + { "get_lock_surface", "noo", ext_session_lock_v1_types + 4 }, + { "unlock_and_destroy", "", ext_session_lock_v1_types + 0 }, +}; + +static const struct wl_message ext_session_lock_v1_events[] = { + { "locked", "", ext_session_lock_v1_types + 0 }, + { "finished", "", ext_session_lock_v1_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface ext_session_lock_v1_interface = { + "ext_session_lock_v1", 1, + 3, ext_session_lock_v1_requests, + 2, ext_session_lock_v1_events, +}; + +static const struct wl_message ext_session_lock_surface_v1_requests[] = { + { "destroy", "", ext_session_lock_v1_types + 0 }, + { "ack_configure", "u", ext_session_lock_v1_types + 0 }, +}; + +static const struct wl_message ext_session_lock_surface_v1_events[] = { + { "configure", "uuu", ext_session_lock_v1_types + 0 }, +}; + +WL_PRIVATE const struct wl_interface ext_session_lock_surface_v1_interface = { + "ext_session_lock_surface_v1", 1, + 2, ext_session_lock_surface_v1_requests, + 1, ext_session_lock_surface_v1_events, +}; + diff --git a/driver/wayland-protocols/ext-session-lock-v1.xml b/driver/wayland-protocols/ext-session-lock-v1.xml new file mode 100644 index 000000000..19c12d26c --- /dev/null +++ b/driver/wayland-protocols/ext-session-lock-v1.xml @@ -0,0 +1,328 @@ + + + + Copyright 2021 Isaac Freund + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + + + This protocol allows for a privileged Wayland client to lock the session + and display arbitrary graphics while the session is locked. + + The compositor may choose to restrict this protocol to a special client + launched by the compositor itself or expose it to all privileged clients, + this is compositor policy. + + The client is responsible for performing authentication and informing the + compositor when the session should be unlocked. If the client dies while + the session is locked the session remains locked, possibly permanently + depending on compositor policy. + + The key words "must", "must not", "required", "shall", "shall not", + "should", "should not", "recommended", "may", and "optional" in this + document are to be interpreted as described in IETF RFC 2119. + + Warning! The protocol described in this file is currently in the + testing phase. Backward compatible changes may be added together with + the corresponding interface version bump. Backward incompatible changes + can only be done by creating a new major version of the extension. + + + + + This interface is used to request that the session be locked. + + + + + This informs the compositor that the session lock manager object will + no longer be used. Existing objects created through this interface + remain valid. + + + + + + This request creates a session lock and asks the compositor to lock the + session. The compositor will send either the ext_session_lock_v1.locked + or ext_session_lock_v1.finished event on the created object in + response to this request. + + + + + + + + In response to the creation of this object the compositor must send + either the locked or finished event. + + The locked event indicates that the session is locked. This means + that the compositor must stop rendering and providing input to normal + clients. Instead the compositor must blank all outputs with an opaque + color such that their normal content is fully hidden. + + The only surfaces that should be rendered while the session is locked + are the lock surfaces created through this interface and optionally, + at the compositor's discretion, special privileged surfaces such as + input methods or portions of desktop shell UIs. + + The locked event must not be sent until a new "locked" frame (either + from a session lock surface or the compositor blanking the output) has + been presented on all outputs and no security sensitive normal/unlocked + content is possibly visible. + + The finished event should be sent immediately on creation of this + object if the compositor decides that the locked event will not be sent. + + The compositor may wait for the client to create and render session lock + surfaces before sending the locked event to avoid displaying intermediate + blank frames. However, it must impose a reasonable time limit if + waiting and send the locked event as soon as the hard requirements + described above can be met if the time limit expires. Clients should + immediately create lock surfaces for all outputs on creation of this + object to make this possible. + + This behavior of the locked event is required in order to prevent + possible race conditions with clients that wish to suspend the system + or similar after locking the session. Without these semantics, clients + triggering a suspend after receiving the locked event would race with + the first "locked" frame being presented and normal/unlocked frames + might be briefly visible as the system is resumed if the suspend + operation wins the race. + + If the client dies while the session is locked, the compositor must not + unlock the session in response. It is acceptable for the session to be + permanently locked if this happens. The compositor may choose to continue + to display the lock surfaces the client had mapped before it died or + alternatively fall back to a solid color, this is compositor policy. + + Compositors may also allow a secure way to recover the session, the + details of this are compositor policy. Compositors may allow a new + client to create a ext_session_lock_v1 object and take responsibility + for unlocking the session, they may even start a new lock client + instance automatically. + + + + + + + + + + + + + This informs the compositor that the lock object will no longer be + used. Existing objects created through this interface remain valid. + + After this request is made, lock surfaces created through this object + should be destroyed by the client as they will no longer be used by + the compositor. + + It is a protocol error to make this request if the locked event was + sent, the unlock_and_destroy request must be used instead. + + + + + + This client is now responsible for displaying graphics while the + session is locked and deciding when to unlock the session. + + The locked event must not be sent until a new "locked" frame has been + presented on all outputs and no security sensitive normal/unlocked + content is possibly visible. + + If this event is sent, making the destroy request is a protocol error, + the lock object must be destroyed using the unlock_and_destroy request. + + + + + + The compositor has decided that the session lock should be destroyed + as it will no longer be used by the compositor. Exactly when this + event is sent is compositor policy, but it must never be sent more + than once for a given session lock object. + + This might be sent because there is already another ext_session_lock_v1 + object held by a client, or the compositor has decided to deny the + request to lock the session for some other reason. This might also + be sent because the compositor implements some alternative, secure + way to authenticate and unlock the session. + + The finished event should be sent immediately on creation of this + object if the compositor decides that the locked event will not + be sent. + + If the locked event is sent on creation of this object the finished + event may still be sent at some later time in this object's + lifetime. This is compositor policy. + + Upon receiving this event, the client should make either the destroy + request or the unlock_and_destroy request, depending on whether or + not the locked event was received on this object. + + + + + + The client is expected to create lock surfaces for all outputs + currently present and any new outputs as they are advertised. These + won't be displayed by the compositor unless the lock is successful + and the locked event is sent. + + Providing a wl_surface which already has a role or already has a buffer + attached or committed is a protocol error, as is attaching/committing + a buffer before the first ext_session_lock_surface_v1.configure event. + + Attempting to create more than one lock surface for a given output + is a duplicate_output protocol error. + + + + + + + + + This request indicates that the session should be unlocked, for + example because the user has entered their password and it has been + verified by the client. + + This request also informs the compositor that the lock object will + no longer be used and should be destroyed. Existing objects created + through this interface remain valid. + + After this request is made, lock surfaces created through this object + should be destroyed by the client as they will no longer be used by + the compositor. + + It is a protocol error to make this request if the locked event has + not been sent. In that case, the lock object must be destroyed using + the destroy request. + + Note that a correct client that wishes to exit directly after unlocking + the session must use the wl_display.sync request to ensure the server + receives and processes the unlock_and_destroy request. Otherwise + there is no guarantee that the server has unlocked the session due + to the asynchronous nature of the Wayland protocol. For example, + the server might terminate the client with a protocol error before + it processes the unlock_and_destroy request. + + + + + + + The client may use lock surfaces to display a screensaver, render a + dialog to enter a password and unlock the session, or however else it + sees fit. + + On binding this interface the compositor will immediately send the + first configure event. After making the ack_configure request in + response to this event the client should attach and commit the first + buffer. Committing the surface before acking the first configure is a + protocol error. Committing the surface with a null buffer at any time + is a protocol error. + + The compositor is free to handle keyboard/pointer focus for lock + surfaces however it chooses. A reasonable way to do this would be to + give the first lock surface created keyboard focus and change keyboard + focus if the user clicks on other surfaces. + + + + + + + + + + + + This informs the compositor that the lock surface object will no + longer be used. + + It is recommended for a lock client to destroy lock surfaces if + their corresponding wl_output global is removed. + + If a lock surface on an active output is destroyed before the + ext_session_lock_v1.unlock_and_destroy event is sent, the compositor + must fall back to rendering a solid color. + + + + + + When a configure event is received, if a client commits the surface + in response to the configure event, then the client must make an + ack_configure request sometime before the commit request, passing + along the serial of the configure event. + + If the client receives multiple configure events before it can + respond to one, it only has to ack the last configure event. + + A client is not required to commit immediately after sending an + ack_configure request - it may even ack_configure several times + before its next surface commit. + + A client may send multiple ack_configure requests before committing, + but only the last request sent before a commit indicates which + configure event the client really is responding to. + + Sending an ack_configure request consumes the configure event + referenced by the given serial, as well as all older configure events + sent on this object. + + It is a protocol error to issue multiple ack_configure requests + referencing the same configure event or to issue an ack_configure + request referencing a configure event older than the last configure + event acked for a given lock surface. + + + + + + + This event is sent once on binding the interface and may be sent again + at the compositor's discretion, for example if output geometry changes. + + The width and height are in surface-local coordinates and are exact + requirements. Failing to match these surface dimensions in the next + commit after acking a configure is a protocol error. + + + + + + + diff --git a/driver/wayland-protocols/xdg-shell-v1-client-protocol.h b/driver/wayland-protocols/xdg-shell-v1-client-protocol.h deleted file mode 100644 index db577563a..000000000 --- a/driver/wayland-protocols/xdg-shell-v1-client-protocol.h +++ /dev/null @@ -1,2381 +0,0 @@ -/* Generated by wayland-scanner 1.23.1 */ - -#ifndef XDG_SHELL_CLIENT_PROTOCOL_H -#define XDG_SHELL_CLIENT_PROTOCOL_H - -#include -#include -#include "wayland-client.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @page page_xdg_shell The xdg_shell protocol - * @section page_ifaces_xdg_shell Interfaces - * - @subpage page_iface_xdg_wm_base - create desktop-style surfaces - * - @subpage page_iface_xdg_positioner - child surface positioner - * - @subpage page_iface_xdg_surface - desktop user interface surface base interface - * - @subpage page_iface_xdg_toplevel - toplevel surface - * - @subpage page_iface_xdg_popup - short-lived, popup surfaces for menus - * @section page_copyright_xdg_shell Copyright - *
- *
- * Copyright © 2008-2013 Kristian Høgsberg
- * Copyright © 2013      Rafael Antognolli
- * Copyright © 2013      Jasper St. Pierre
- * Copyright © 2010-2013 Intel Corporation
- * Copyright © 2015-2017 Samsung Electronics Co., Ltd
- * Copyright © 2015-2017 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- * 
- */ -struct wl_output; -struct wl_seat; -struct wl_surface; -struct xdg_popup; -struct xdg_positioner; -struct xdg_surface; -struct xdg_toplevel; -struct xdg_wm_base; - -#ifndef XDG_WM_BASE_INTERFACE -#define XDG_WM_BASE_INTERFACE -/** - * @page page_iface_xdg_wm_base xdg_wm_base - * @section page_iface_xdg_wm_base_desc Description - * - * The xdg_wm_base interface is exposed as a global object enabling clients - * to turn their wl_surfaces into windows in a desktop environment. It - * defines the basic functionality needed for clients and the compositor to - * create windows that can be dragged, resized, maximized, etc, as well as - * creating transient windows such as popup menus. - * @section page_iface_xdg_wm_base_api API - * See @ref iface_xdg_wm_base. - */ -/** - * @defgroup iface_xdg_wm_base The xdg_wm_base interface - * - * The xdg_wm_base interface is exposed as a global object enabling clients - * to turn their wl_surfaces into windows in a desktop environment. It - * defines the basic functionality needed for clients and the compositor to - * create windows that can be dragged, resized, maximized, etc, as well as - * creating transient windows such as popup menus. - */ -extern const struct wl_interface xdg_wm_base_interface; -#endif -#ifndef XDG_POSITIONER_INTERFACE -#define XDG_POSITIONER_INTERFACE -/** - * @page page_iface_xdg_positioner xdg_positioner - * @section page_iface_xdg_positioner_desc Description - * - * The xdg_positioner provides a collection of rules for the placement of a - * child surface relative to a parent surface. Rules can be defined to ensure - * the child surface remains within the visible area's borders, and to - * specify how the child surface changes its position, such as sliding along - * an axis, or flipping around a rectangle. These positioner-created rules are - * constrained by the requirement that a child surface must intersect with or - * be at least partially adjacent to its parent surface. - * - * See the various requests for details about possible rules. - * - * At the time of the request, the compositor makes a copy of the rules - * specified by the xdg_positioner. Thus, after the request is complete the - * xdg_positioner object can be destroyed or reused; further changes to the - * object will have no effect on previous usages. - * - * For an xdg_positioner object to be considered complete, it must have a - * non-zero size set by set_size, and a non-zero anchor rectangle set by - * set_anchor_rect. Passing an incomplete xdg_positioner object when - * positioning a surface raises an invalid_positioner error. - * @section page_iface_xdg_positioner_api API - * See @ref iface_xdg_positioner. - */ -/** - * @defgroup iface_xdg_positioner The xdg_positioner interface - * - * The xdg_positioner provides a collection of rules for the placement of a - * child surface relative to a parent surface. Rules can be defined to ensure - * the child surface remains within the visible area's borders, and to - * specify how the child surface changes its position, such as sliding along - * an axis, or flipping around a rectangle. These positioner-created rules are - * constrained by the requirement that a child surface must intersect with or - * be at least partially adjacent to its parent surface. - * - * See the various requests for details about possible rules. - * - * At the time of the request, the compositor makes a copy of the rules - * specified by the xdg_positioner. Thus, after the request is complete the - * xdg_positioner object can be destroyed or reused; further changes to the - * object will have no effect on previous usages. - * - * For an xdg_positioner object to be considered complete, it must have a - * non-zero size set by set_size, and a non-zero anchor rectangle set by - * set_anchor_rect. Passing an incomplete xdg_positioner object when - * positioning a surface raises an invalid_positioner error. - */ -extern const struct wl_interface xdg_positioner_interface; -#endif -#ifndef XDG_SURFACE_INTERFACE -#define XDG_SURFACE_INTERFACE -/** - * @page page_iface_xdg_surface xdg_surface - * @section page_iface_xdg_surface_desc Description - * - * An interface that may be implemented by a wl_surface, for - * implementations that provide a desktop-style user interface. - * - * It provides a base set of functionality required to construct user - * interface elements requiring management by the compositor, such as - * toplevel windows, menus, etc. The types of functionality are split into - * xdg_surface roles. - * - * Creating an xdg_surface does not set the role for a wl_surface. In order - * to map an xdg_surface, the client must create a role-specific object - * using, e.g., get_toplevel, get_popup. The wl_surface for any given - * xdg_surface can have at most one role, and may not be assigned any role - * not based on xdg_surface. - * - * A role must be assigned before any other requests are made to the - * xdg_surface object. - * - * The client must call wl_surface.commit on the corresponding wl_surface - * for the xdg_surface state to take effect. - * - * Creating an xdg_surface from a wl_surface which has a buffer attached or - * committed is a client error, and any attempts by a client to attach or - * manipulate a buffer prior to the first xdg_surface.configure call must - * also be treated as errors. - * - * After creating a role-specific object and setting it up (e.g. by sending - * the title, app ID, size constraints, parent, etc), the client must - * perform an initial commit without any buffer attached. The compositor - * will reply with initial wl_surface state such as - * wl_surface.preferred_buffer_scale followed by an xdg_surface.configure - * event. The client must acknowledge it and is then allowed to attach a - * buffer to map the surface. - * - * Mapping an xdg_surface-based role surface is defined as making it - * possible for the surface to be shown by the compositor. Note that - * a mapped surface is not guaranteed to be visible once it is mapped. - * - * For an xdg_surface to be mapped by the compositor, the following - * conditions must be met: - * (1) the client has assigned an xdg_surface-based role to the surface - * (2) the client has set and committed the xdg_surface state and the - * role-dependent state to the surface - * (3) the client has committed a buffer to the surface - * - * A newly-unmapped surface is considered to have met condition (1) out - * of the 3 required conditions for mapping a surface if its role surface - * has not been destroyed, i.e. the client must perform the initial commit - * again before attaching a buffer. - * @section page_iface_xdg_surface_api API - * See @ref iface_xdg_surface. - */ -/** - * @defgroup iface_xdg_surface The xdg_surface interface - * - * An interface that may be implemented by a wl_surface, for - * implementations that provide a desktop-style user interface. - * - * It provides a base set of functionality required to construct user - * interface elements requiring management by the compositor, such as - * toplevel windows, menus, etc. The types of functionality are split into - * xdg_surface roles. - * - * Creating an xdg_surface does not set the role for a wl_surface. In order - * to map an xdg_surface, the client must create a role-specific object - * using, e.g., get_toplevel, get_popup. The wl_surface for any given - * xdg_surface can have at most one role, and may not be assigned any role - * not based on xdg_surface. - * - * A role must be assigned before any other requests are made to the - * xdg_surface object. - * - * The client must call wl_surface.commit on the corresponding wl_surface - * for the xdg_surface state to take effect. - * - * Creating an xdg_surface from a wl_surface which has a buffer attached or - * committed is a client error, and any attempts by a client to attach or - * manipulate a buffer prior to the first xdg_surface.configure call must - * also be treated as errors. - * - * After creating a role-specific object and setting it up (e.g. by sending - * the title, app ID, size constraints, parent, etc), the client must - * perform an initial commit without any buffer attached. The compositor - * will reply with initial wl_surface state such as - * wl_surface.preferred_buffer_scale followed by an xdg_surface.configure - * event. The client must acknowledge it and is then allowed to attach a - * buffer to map the surface. - * - * Mapping an xdg_surface-based role surface is defined as making it - * possible for the surface to be shown by the compositor. Note that - * a mapped surface is not guaranteed to be visible once it is mapped. - * - * For an xdg_surface to be mapped by the compositor, the following - * conditions must be met: - * (1) the client has assigned an xdg_surface-based role to the surface - * (2) the client has set and committed the xdg_surface state and the - * role-dependent state to the surface - * (3) the client has committed a buffer to the surface - * - * A newly-unmapped surface is considered to have met condition (1) out - * of the 3 required conditions for mapping a surface if its role surface - * has not been destroyed, i.e. the client must perform the initial commit - * again before attaching a buffer. - */ -extern const struct wl_interface xdg_surface_interface; -#endif -#ifndef XDG_TOPLEVEL_INTERFACE -#define XDG_TOPLEVEL_INTERFACE -/** - * @page page_iface_xdg_toplevel xdg_toplevel - * @section page_iface_xdg_toplevel_desc Description - * - * This interface defines an xdg_surface role which allows a surface to, - * among other things, set window-like properties such as maximize, - * fullscreen, and minimize, set application-specific metadata like title and - * id, and well as trigger user interactive operations such as interactive - * resize and move. - * - * A xdg_toplevel by default is responsible for providing the full intended - * visual representation of the toplevel, which depending on the window - * state, may mean things like a title bar, window controls and drop shadow. - * - * Unmapping an xdg_toplevel means that the surface cannot be shown - * by the compositor until it is explicitly mapped again. - * All active operations (e.g., move, resize) are canceled and all - * attributes (e.g. title, state, stacking, ...) are discarded for - * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to - * the state it had right after xdg_surface.get_toplevel. The client - * can re-map the toplevel by performing a commit without any buffer - * attached, waiting for a configure event and handling it as usual (see - * xdg_surface description). - * - * Attaching a null buffer to a toplevel unmaps the surface. - * @section page_iface_xdg_toplevel_api API - * See @ref iface_xdg_toplevel. - */ -/** - * @defgroup iface_xdg_toplevel The xdg_toplevel interface - * - * This interface defines an xdg_surface role which allows a surface to, - * among other things, set window-like properties such as maximize, - * fullscreen, and minimize, set application-specific metadata like title and - * id, and well as trigger user interactive operations such as interactive - * resize and move. - * - * A xdg_toplevel by default is responsible for providing the full intended - * visual representation of the toplevel, which depending on the window - * state, may mean things like a title bar, window controls and drop shadow. - * - * Unmapping an xdg_toplevel means that the surface cannot be shown - * by the compositor until it is explicitly mapped again. - * All active operations (e.g., move, resize) are canceled and all - * attributes (e.g. title, state, stacking, ...) are discarded for - * an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to - * the state it had right after xdg_surface.get_toplevel. The client - * can re-map the toplevel by performing a commit without any buffer - * attached, waiting for a configure event and handling it as usual (see - * xdg_surface description). - * - * Attaching a null buffer to a toplevel unmaps the surface. - */ -extern const struct wl_interface xdg_toplevel_interface; -#endif -#ifndef XDG_POPUP_INTERFACE -#define XDG_POPUP_INTERFACE -/** - * @page page_iface_xdg_popup xdg_popup - * @section page_iface_xdg_popup_desc Description - * - * A popup surface is a short-lived, temporary surface. It can be used to - * implement for example menus, popovers, tooltips and other similar user - * interface concepts. - * - * A popup can be made to take an explicit grab. See xdg_popup.grab for - * details. - * - * When the popup is dismissed, a popup_done event will be sent out, and at - * the same time the surface will be unmapped. See the xdg_popup.popup_done - * event for details. - * - * Explicitly destroying the xdg_popup object will also dismiss the popup and - * unmap the surface. Clients that want to dismiss the popup when another - * surface of their own is clicked should dismiss the popup using the destroy - * request. - * - * A newly created xdg_popup will be stacked on top of all previously created - * xdg_popup surfaces associated with the same xdg_toplevel. - * - * The parent of an xdg_popup must be mapped (see the xdg_surface - * description) before the xdg_popup itself. - * - * The client must call wl_surface.commit on the corresponding wl_surface - * for the xdg_popup state to take effect. - * @section page_iface_xdg_popup_api API - * See @ref iface_xdg_popup. - */ -/** - * @defgroup iface_xdg_popup The xdg_popup interface - * - * A popup surface is a short-lived, temporary surface. It can be used to - * implement for example menus, popovers, tooltips and other similar user - * interface concepts. - * - * A popup can be made to take an explicit grab. See xdg_popup.grab for - * details. - * - * When the popup is dismissed, a popup_done event will be sent out, and at - * the same time the surface will be unmapped. See the xdg_popup.popup_done - * event for details. - * - * Explicitly destroying the xdg_popup object will also dismiss the popup and - * unmap the surface. Clients that want to dismiss the popup when another - * surface of their own is clicked should dismiss the popup using the destroy - * request. - * - * A newly created xdg_popup will be stacked on top of all previously created - * xdg_popup surfaces associated with the same xdg_toplevel. - * - * The parent of an xdg_popup must be mapped (see the xdg_surface - * description) before the xdg_popup itself. - * - * The client must call wl_surface.commit on the corresponding wl_surface - * for the xdg_popup state to take effect. - */ -extern const struct wl_interface xdg_popup_interface; -#endif - -#ifndef XDG_WM_BASE_ERROR_ENUM -#define XDG_WM_BASE_ERROR_ENUM -enum xdg_wm_base_error { - /** - * given wl_surface has another role - */ - XDG_WM_BASE_ERROR_ROLE = 0, - /** - * xdg_wm_base was destroyed before children - */ - XDG_WM_BASE_ERROR_DEFUNCT_SURFACES = 1, - /** - * the client tried to map or destroy a non-topmost popup - */ - XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP = 2, - /** - * the client specified an invalid popup parent surface - */ - XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT = 3, - /** - * the client provided an invalid surface state - */ - XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE = 4, - /** - * the client provided an invalid positioner - */ - XDG_WM_BASE_ERROR_INVALID_POSITIONER = 5, - /** - * the client didn’t respond to a ping event in time - */ - XDG_WM_BASE_ERROR_UNRESPONSIVE = 6, -}; -#endif /* XDG_WM_BASE_ERROR_ENUM */ - -/** - * @ingroup iface_xdg_wm_base - * @struct xdg_wm_base_listener - */ -struct xdg_wm_base_listener { - /** - * check if the client is alive - * - * The ping event asks the client if it's still alive. Pass the - * serial specified in the event back to the compositor by sending - * a "pong" request back with the specified serial. See - * xdg_wm_base.pong. - * - * Compositors can use this to determine if the client is still - * alive. It's unspecified what will happen if the client doesn't - * respond to the ping request, or in what timeframe. Clients - * should try to respond in a reasonable amount of time. The - * “unresponsive” error is provided for compositors that wish - * to disconnect unresponsive clients. - * - * A compositor is free to ping in any way it wants, but a client - * must always respond to any xdg_wm_base object it created. - * @param serial pass this to the pong request - */ - void (*ping)(void *data, - struct xdg_wm_base *xdg_wm_base, - uint32_t serial); -}; - -/** - * @ingroup iface_xdg_wm_base - */ -static inline int -xdg_wm_base_add_listener(struct xdg_wm_base *xdg_wm_base, - const struct xdg_wm_base_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) xdg_wm_base, - (void (**)(void)) listener, data); -} - -#define XDG_WM_BASE_DESTROY 0 -#define XDG_WM_BASE_CREATE_POSITIONER 1 -#define XDG_WM_BASE_GET_XDG_SURFACE 2 -#define XDG_WM_BASE_PONG 3 - -/** - * @ingroup iface_xdg_wm_base - */ -#define XDG_WM_BASE_PING_SINCE_VERSION 1 - -/** - * @ingroup iface_xdg_wm_base - */ -#define XDG_WM_BASE_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_wm_base - */ -#define XDG_WM_BASE_CREATE_POSITIONER_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_wm_base - */ -#define XDG_WM_BASE_GET_XDG_SURFACE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_wm_base - */ -#define XDG_WM_BASE_PONG_SINCE_VERSION 1 - -/** @ingroup iface_xdg_wm_base */ -static inline void -xdg_wm_base_set_user_data(struct xdg_wm_base *xdg_wm_base, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) xdg_wm_base, user_data); -} - -/** @ingroup iface_xdg_wm_base */ -static inline void * -xdg_wm_base_get_user_data(struct xdg_wm_base *xdg_wm_base) -{ - return wl_proxy_get_user_data((struct wl_proxy *) xdg_wm_base); -} - -static inline uint32_t -xdg_wm_base_get_version(struct xdg_wm_base *xdg_wm_base) -{ - return wl_proxy_get_version((struct wl_proxy *) xdg_wm_base); -} - -/** - * @ingroup iface_xdg_wm_base - * - * Destroy this xdg_wm_base object. - * - * Destroying a bound xdg_wm_base object while there are surfaces - * still alive created by this xdg_wm_base object instance is illegal - * and will result in a defunct_surfaces error. - */ -static inline void -xdg_wm_base_destroy(struct xdg_wm_base *xdg_wm_base) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base, - XDG_WM_BASE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_xdg_wm_base - * - * Create a positioner object. A positioner object is used to position - * surfaces relative to some parent surface. See the interface description - * and xdg_surface.get_popup for details. - */ -static inline struct xdg_positioner * -xdg_wm_base_create_positioner(struct xdg_wm_base *xdg_wm_base) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base, - XDG_WM_BASE_CREATE_POSITIONER, &xdg_positioner_interface, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, NULL); - - return (struct xdg_positioner *) id; -} - -/** - * @ingroup iface_xdg_wm_base - * - * This creates an xdg_surface for the given surface. While xdg_surface - * itself is not a role, the corresponding surface may only be assigned - * a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is - * illegal to create an xdg_surface for a wl_surface which already has an - * assigned role and this will result in a role error. - * - * This creates an xdg_surface for the given surface. An xdg_surface is - * used as basis to define a role to a given surface, such as xdg_toplevel - * or xdg_popup. It also manages functionality shared between xdg_surface - * based surface roles. - * - * See the documentation of xdg_surface for more details about what an - * xdg_surface is and how it is used. - */ -static inline struct xdg_surface * -xdg_wm_base_get_xdg_surface(struct xdg_wm_base *xdg_wm_base, struct wl_surface *surface) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base, - XDG_WM_BASE_GET_XDG_SURFACE, &xdg_surface_interface, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, NULL, surface); - - return (struct xdg_surface *) id; -} - -/** - * @ingroup iface_xdg_wm_base - * - * A client must respond to a ping event with a pong request or - * the client may be deemed unresponsive. See xdg_wm_base.ping - * and xdg_wm_base.error.unresponsive. - */ -static inline void -xdg_wm_base_pong(struct xdg_wm_base *xdg_wm_base, uint32_t serial) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_wm_base, - XDG_WM_BASE_PONG, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_wm_base), 0, serial); -} - -#ifndef XDG_POSITIONER_ERROR_ENUM -#define XDG_POSITIONER_ERROR_ENUM -enum xdg_positioner_error { - /** - * invalid input provided - */ - XDG_POSITIONER_ERROR_INVALID_INPUT = 0, -}; -#endif /* XDG_POSITIONER_ERROR_ENUM */ - -#ifndef XDG_POSITIONER_ANCHOR_ENUM -#define XDG_POSITIONER_ANCHOR_ENUM -enum xdg_positioner_anchor { - XDG_POSITIONER_ANCHOR_NONE = 0, - XDG_POSITIONER_ANCHOR_TOP = 1, - XDG_POSITIONER_ANCHOR_BOTTOM = 2, - XDG_POSITIONER_ANCHOR_LEFT = 3, - XDG_POSITIONER_ANCHOR_RIGHT = 4, - XDG_POSITIONER_ANCHOR_TOP_LEFT = 5, - XDG_POSITIONER_ANCHOR_BOTTOM_LEFT = 6, - XDG_POSITIONER_ANCHOR_TOP_RIGHT = 7, - XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT = 8, -}; -#endif /* XDG_POSITIONER_ANCHOR_ENUM */ - -#ifndef XDG_POSITIONER_GRAVITY_ENUM -#define XDG_POSITIONER_GRAVITY_ENUM -enum xdg_positioner_gravity { - XDG_POSITIONER_GRAVITY_NONE = 0, - XDG_POSITIONER_GRAVITY_TOP = 1, - XDG_POSITIONER_GRAVITY_BOTTOM = 2, - XDG_POSITIONER_GRAVITY_LEFT = 3, - XDG_POSITIONER_GRAVITY_RIGHT = 4, - XDG_POSITIONER_GRAVITY_TOP_LEFT = 5, - XDG_POSITIONER_GRAVITY_BOTTOM_LEFT = 6, - XDG_POSITIONER_GRAVITY_TOP_RIGHT = 7, - XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT = 8, -}; -#endif /* XDG_POSITIONER_GRAVITY_ENUM */ - -#ifndef XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM -#define XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM -/** - * @ingroup iface_xdg_positioner - * constraint adjustments - * - * The constraint adjustment value define ways the compositor will adjust - * the position of the surface, if the unadjusted position would result - * in the surface being partly constrained. - * - * Whether a surface is considered 'constrained' is left to the compositor - * to determine. For example, the surface may be partly outside the - * compositor's defined 'work area', thus necessitating the child surface's - * position be adjusted until it is entirely inside the work area. - * - * The adjustments can be combined, according to a defined precedence: 1) - * Flip, 2) Slide, 3) Resize. - */ -enum xdg_positioner_constraint_adjustment { - /** - * don't move the child surface when constrained - * - * Don't alter the surface position even if it is constrained on - * some axis, for example partially outside the edge of an output. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE = 0, - /** - * move along the x axis until unconstrained - * - * Slide the surface along the x axis until it is no longer - * constrained. - * - * First try to slide towards the direction of the gravity on the x - * axis until either the edge in the opposite direction of the - * gravity is unconstrained or the edge in the direction of the - * gravity is constrained. - * - * Then try to slide towards the opposite direction of the gravity - * on the x axis until either the edge in the direction of the - * gravity is unconstrained or the edge in the opposite direction - * of the gravity is constrained. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1, - /** - * move along the y axis until unconstrained - * - * Slide the surface along the y axis until it is no longer - * constrained. - * - * First try to slide towards the direction of the gravity on the y - * axis until either the edge in the opposite direction of the - * gravity is unconstrained or the edge in the direction of the - * gravity is constrained. - * - * Then try to slide towards the opposite direction of the gravity - * on the y axis until either the edge in the direction of the - * gravity is unconstrained or the edge in the opposite direction - * of the gravity is constrained. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 2, - /** - * invert the anchor and gravity on the x axis - * - * Invert the anchor and gravity on the x axis if the surface is - * constrained on the x axis. For example, if the left edge of the - * surface is constrained, the gravity is 'left' and the anchor is - * 'left', change the gravity to 'right' and the anchor to 'right'. - * - * If the adjusted position also ends up being constrained, the - * resulting position of the flip_x adjustment will be the one - * before the adjustment. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X = 4, - /** - * invert the anchor and gravity on the y axis - * - * Invert the anchor and gravity on the y axis if the surface is - * constrained on the y axis. For example, if the bottom edge of - * the surface is constrained, the gravity is 'bottom' and the - * anchor is 'bottom', change the gravity to 'top' and the anchor - * to 'top'. - * - * The adjusted position is calculated given the original anchor - * rectangle and offset, but with the new flipped anchor and - * gravity values. - * - * If the adjusted position also ends up being constrained, the - * resulting position of the flip_y adjustment will be the one - * before the adjustment. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y = 8, - /** - * horizontally resize the surface - * - * Resize the surface horizontally so that it is completely - * unconstrained. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X = 16, - /** - * vertically resize the surface - * - * Resize the surface vertically so that it is completely - * unconstrained. - */ - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 32, -}; -#endif /* XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_ENUM */ - -#define XDG_POSITIONER_DESTROY 0 -#define XDG_POSITIONER_SET_SIZE 1 -#define XDG_POSITIONER_SET_ANCHOR_RECT 2 -#define XDG_POSITIONER_SET_ANCHOR 3 -#define XDG_POSITIONER_SET_GRAVITY 4 -#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT 5 -#define XDG_POSITIONER_SET_OFFSET 6 -#define XDG_POSITIONER_SET_REACTIVE 7 -#define XDG_POSITIONER_SET_PARENT_SIZE 8 -#define XDG_POSITIONER_SET_PARENT_CONFIGURE 9 - - -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_SIZE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_ANCHOR_RECT_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_ANCHOR_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_GRAVITY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_OFFSET_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_REACTIVE_SINCE_VERSION 3 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_PARENT_SIZE_SINCE_VERSION 3 -/** - * @ingroup iface_xdg_positioner - */ -#define XDG_POSITIONER_SET_PARENT_CONFIGURE_SINCE_VERSION 3 - -/** @ingroup iface_xdg_positioner */ -static inline void -xdg_positioner_set_user_data(struct xdg_positioner *xdg_positioner, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) xdg_positioner, user_data); -} - -/** @ingroup iface_xdg_positioner */ -static inline void * -xdg_positioner_get_user_data(struct xdg_positioner *xdg_positioner) -{ - return wl_proxy_get_user_data((struct wl_proxy *) xdg_positioner); -} - -static inline uint32_t -xdg_positioner_get_version(struct xdg_positioner *xdg_positioner) -{ - return wl_proxy_get_version((struct wl_proxy *) xdg_positioner); -} - -/** - * @ingroup iface_xdg_positioner - * - * Notify the compositor that the xdg_positioner will no longer be used. - */ -static inline void -xdg_positioner_destroy(struct xdg_positioner *xdg_positioner) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, - XDG_POSITIONER_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_xdg_positioner - * - * Set the size of the surface that is to be positioned with the positioner - * object. The size is in surface-local coordinates and corresponds to the - * window geometry. See xdg_surface.set_window_geometry. - * - * If a zero or negative size is set the invalid_input error is raised. - */ -static inline void -xdg_positioner_set_size(struct xdg_positioner *xdg_positioner, int32_t width, int32_t height) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, - XDG_POSITIONER_SET_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, width, height); -} - -/** - * @ingroup iface_xdg_positioner - * - * Specify the anchor rectangle within the parent surface that the child - * surface will be placed relative to. The rectangle is relative to the - * window geometry as defined by xdg_surface.set_window_geometry of the - * parent surface. - * - * When the xdg_positioner object is used to position a child surface, the - * anchor rectangle may not extend outside the window geometry of the - * positioned child's parent surface. - * - * If a negative size is set the invalid_input error is raised. - */ -static inline void -xdg_positioner_set_anchor_rect(struct xdg_positioner *xdg_positioner, int32_t x, int32_t y, int32_t width, int32_t height) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, - XDG_POSITIONER_SET_ANCHOR_RECT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, x, y, width, height); -} - -/** - * @ingroup iface_xdg_positioner - * - * Defines the anchor point for the anchor rectangle. The specified anchor - * is used derive an anchor point that the child surface will be - * positioned relative to. If a corner anchor is set (e.g. 'top_left' or - * 'bottom_right'), the anchor point will be at the specified corner; - * otherwise, the derived anchor point will be centered on the specified - * edge, or in the center of the anchor rectangle if no edge is specified. - */ -static inline void -xdg_positioner_set_anchor(struct xdg_positioner *xdg_positioner, uint32_t anchor) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, - XDG_POSITIONER_SET_ANCHOR, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, anchor); -} - -/** - * @ingroup iface_xdg_positioner - * - * Defines in what direction a surface should be positioned, relative to - * the anchor point of the parent surface. If a corner gravity is - * specified (e.g. 'bottom_right' or 'top_left'), then the child surface - * will be placed towards the specified gravity; otherwise, the child - * surface will be centered over the anchor point on any axis that had no - * gravity specified. If the gravity is not in the ‘gravity’ enum, an - * invalid_input error is raised. - */ -static inline void -xdg_positioner_set_gravity(struct xdg_positioner *xdg_positioner, uint32_t gravity) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, - XDG_POSITIONER_SET_GRAVITY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, gravity); -} - -/** - * @ingroup iface_xdg_positioner - * - * Specify how the window should be positioned if the originally intended - * position caused the surface to be constrained, meaning at least - * partially outside positioning boundaries set by the compositor. The - * adjustment is set by constructing a bitmask describing the adjustment to - * be made when the surface is constrained on that axis. - * - * If no bit for one axis is set, the compositor will assume that the child - * surface should not change its position on that axis when constrained. - * - * If more than one bit for one axis is set, the order of how adjustments - * are applied is specified in the corresponding adjustment descriptions. - * - * The default adjustment is none. - */ -static inline void -xdg_positioner_set_constraint_adjustment(struct xdg_positioner *xdg_positioner, uint32_t constraint_adjustment) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, - XDG_POSITIONER_SET_CONSTRAINT_ADJUSTMENT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, constraint_adjustment); -} - -/** - * @ingroup iface_xdg_positioner - * - * Specify the surface position offset relative to the position of the - * anchor on the anchor rectangle and the anchor on the surface. For - * example if the anchor of the anchor rectangle is at (x, y), the surface - * has the gravity bottom|right, and the offset is (ox, oy), the calculated - * surface position will be (x + ox, y + oy). The offset position of the - * surface is the one used for constraint testing. See - * set_constraint_adjustment. - * - * An example use case is placing a popup menu on top of a user interface - * element, while aligning the user interface element of the parent surface - * with some user interface element placed somewhere in the popup surface. - */ -static inline void -xdg_positioner_set_offset(struct xdg_positioner *xdg_positioner, int32_t x, int32_t y) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, - XDG_POSITIONER_SET_OFFSET, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, x, y); -} - -/** - * @ingroup iface_xdg_positioner - * - * When set reactive, the surface is reconstrained if the conditions used - * for constraining changed, e.g. the parent window moved. - * - * If the conditions changed and the popup was reconstrained, an - * xdg_popup.configure event is sent with updated geometry, followed by an - * xdg_surface.configure event. - */ -static inline void -xdg_positioner_set_reactive(struct xdg_positioner *xdg_positioner) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, - XDG_POSITIONER_SET_REACTIVE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0); -} - -/** - * @ingroup iface_xdg_positioner - * - * Set the parent window geometry the compositor should use when - * positioning the popup. The compositor may use this information to - * determine the future state the popup should be constrained using. If - * this doesn't match the dimension of the parent the popup is eventually - * positioned against, the behavior is undefined. - * - * The arguments are given in the surface-local coordinate space. - */ -static inline void -xdg_positioner_set_parent_size(struct xdg_positioner *xdg_positioner, int32_t parent_width, int32_t parent_height) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, - XDG_POSITIONER_SET_PARENT_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, parent_width, parent_height); -} - -/** - * @ingroup iface_xdg_positioner - * - * Set the serial of an xdg_surface.configure event this positioner will be - * used in response to. The compositor may use this information together - * with set_parent_size to determine what future state the popup should be - * constrained using. - */ -static inline void -xdg_positioner_set_parent_configure(struct xdg_positioner *xdg_positioner, uint32_t serial) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_positioner, - XDG_POSITIONER_SET_PARENT_CONFIGURE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_positioner), 0, serial); -} - -#ifndef XDG_SURFACE_ERROR_ENUM -#define XDG_SURFACE_ERROR_ENUM -enum xdg_surface_error { - /** - * Surface was not fully constructed - */ - XDG_SURFACE_ERROR_NOT_CONSTRUCTED = 1, - /** - * Surface was already constructed - */ - XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED = 2, - /** - * Attaching a buffer to an unconfigured surface - */ - XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER = 3, - /** - * Invalid serial number when acking a configure event - */ - XDG_SURFACE_ERROR_INVALID_SERIAL = 4, - /** - * Width or height was zero or negative - */ - XDG_SURFACE_ERROR_INVALID_SIZE = 5, - /** - * Surface was destroyed before its role object - */ - XDG_SURFACE_ERROR_DEFUNCT_ROLE_OBJECT = 6, -}; -#endif /* XDG_SURFACE_ERROR_ENUM */ - -/** - * @ingroup iface_xdg_surface - * @struct xdg_surface_listener - */ -struct xdg_surface_listener { - /** - * suggest a surface change - * - * The configure event marks the end of a configure sequence. A - * configure sequence is a set of one or more events configuring - * the state of the xdg_surface, including the final - * xdg_surface.configure event. - * - * Where applicable, xdg_surface surface roles will during a - * configure sequence extend this event as a latched state sent as - * events before the xdg_surface.configure event. Such events - * should be considered to make up a set of atomically applied - * configuration states, where the xdg_surface.configure commits - * the accumulated state. - * - * Clients should arrange their surface for the new states, and - * then send an ack_configure request with the serial sent in this - * configure event at some point before committing the new surface. - * - * If the client receives multiple configure events before it can - * respond to one, it is free to discard all but the last event it - * received. - * @param serial serial of the configure event - */ - void (*configure)(void *data, - struct xdg_surface *xdg_surface, - uint32_t serial); -}; - -/** - * @ingroup iface_xdg_surface - */ -static inline int -xdg_surface_add_listener(struct xdg_surface *xdg_surface, - const struct xdg_surface_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) xdg_surface, - (void (**)(void)) listener, data); -} - -#define XDG_SURFACE_DESTROY 0 -#define XDG_SURFACE_GET_TOPLEVEL 1 -#define XDG_SURFACE_GET_POPUP 2 -#define XDG_SURFACE_SET_WINDOW_GEOMETRY 3 -#define XDG_SURFACE_ACK_CONFIGURE 4 - -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_CONFIGURE_SINCE_VERSION 1 - -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_GET_TOPLEVEL_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_GET_POPUP_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_SET_WINDOW_GEOMETRY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_surface - */ -#define XDG_SURFACE_ACK_CONFIGURE_SINCE_VERSION 1 - -/** @ingroup iface_xdg_surface */ -static inline void -xdg_surface_set_user_data(struct xdg_surface *xdg_surface, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) xdg_surface, user_data); -} - -/** @ingroup iface_xdg_surface */ -static inline void * -xdg_surface_get_user_data(struct xdg_surface *xdg_surface) -{ - return wl_proxy_get_user_data((struct wl_proxy *) xdg_surface); -} - -static inline uint32_t -xdg_surface_get_version(struct xdg_surface *xdg_surface) -{ - return wl_proxy_get_version((struct wl_proxy *) xdg_surface); -} - -/** - * @ingroup iface_xdg_surface - * - * Destroy the xdg_surface object. An xdg_surface must only be destroyed - * after its role object has been destroyed, otherwise - * a defunct_role_object error is raised. - */ -static inline void -xdg_surface_destroy(struct xdg_surface *xdg_surface) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface, - XDG_SURFACE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_xdg_surface - * - * This creates an xdg_toplevel object for the given xdg_surface and gives - * the associated wl_surface the xdg_toplevel role. - * - * See the documentation of xdg_toplevel for more details about what an - * xdg_toplevel is and how it is used. - */ -static inline struct xdg_toplevel * -xdg_surface_get_toplevel(struct xdg_surface *xdg_surface) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface, - XDG_SURFACE_GET_TOPLEVEL, &xdg_toplevel_interface, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, NULL); - - return (struct xdg_toplevel *) id; -} - -/** - * @ingroup iface_xdg_surface - * - * This creates an xdg_popup object for the given xdg_surface and gives - * the associated wl_surface the xdg_popup role. - * - * If null is passed as a parent, a parent surface must be specified using - * some other protocol, before committing the initial state. - * - * See the documentation of xdg_popup for more details about what an - * xdg_popup is and how it is used. - */ -static inline struct xdg_popup * -xdg_surface_get_popup(struct xdg_surface *xdg_surface, struct xdg_surface *parent, struct xdg_positioner *positioner) -{ - struct wl_proxy *id; - - id = wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface, - XDG_SURFACE_GET_POPUP, &xdg_popup_interface, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, NULL, parent, positioner); - - return (struct xdg_popup *) id; -} - -/** - * @ingroup iface_xdg_surface - * - * The window geometry of a surface is its "visible bounds" from the - * user's perspective. Client-side decorations often have invisible - * portions like drop-shadows which should be ignored for the - * purposes of aligning, placing and constraining windows. - * - * The window geometry is double-buffered state, see wl_surface.commit. - * - * When maintaining a position, the compositor should treat the (x, y) - * coordinate of the window geometry as the top left corner of the window. - * A client changing the (x, y) window geometry coordinate should in - * general not alter the position of the window. - * - * Once the window geometry of the surface is set, it is not possible to - * unset it, and it will remain the same until set_window_geometry is - * called again, even if a new subsurface or buffer is attached. - * - * If never set, the value is the full bounds of the surface, - * including any subsurfaces. This updates dynamically on every - * commit. This unset is meant for extremely simple clients. - * - * The arguments are given in the surface-local coordinate space of - * the wl_surface associated with this xdg_surface, and may extend outside - * of the wl_surface itself to mark parts of the subsurface tree as part of - * the window geometry. - * - * When applied, the effective window geometry will be the set window - * geometry clamped to the bounding rectangle of the combined - * geometry of the surface of the xdg_surface and the associated - * subsurfaces. - * - * The effective geometry will not be recalculated unless a new call to - * set_window_geometry is done and the new pending surface state is - * subsequently applied. - * - * The width and height of the effective window geometry must be - * greater than zero. Setting an invalid size will raise an - * invalid_size error. - */ -static inline void -xdg_surface_set_window_geometry(struct xdg_surface *xdg_surface, int32_t x, int32_t y, int32_t width, int32_t height) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface, - XDG_SURFACE_SET_WINDOW_GEOMETRY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, x, y, width, height); -} - -/** - * @ingroup iface_xdg_surface - * - * When a configure event is received, if a client commits the - * surface in response to the configure event, then the client - * must make an ack_configure request sometime before the commit - * request, passing along the serial of the configure event. - * - * For instance, for toplevel surfaces the compositor might use this - * information to move a surface to the top left only when the client has - * drawn itself for the maximized or fullscreen state. - * - * If the client receives multiple configure events before it - * can respond to one, it only has to ack the last configure event. - * Acking a configure event that was never sent raises an invalid_serial - * error. - * - * A client is not required to commit immediately after sending - * an ack_configure request - it may even ack_configure several times - * before its next surface commit. - * - * A client may send multiple ack_configure requests before committing, but - * only the last request sent before a commit indicates which configure - * event the client really is responding to. - * - * Sending an ack_configure request consumes the serial number sent with - * the request, as well as serial numbers sent by all configure events - * sent on this xdg_surface prior to the configure event referenced by - * the committed serial. - * - * It is an error to issue multiple ack_configure requests referencing a - * serial from the same configure event, or to issue an ack_configure - * request referencing a serial from a configure event issued before the - * event identified by the last ack_configure request for the same - * xdg_surface. Doing so will raise an invalid_serial error. - */ -static inline void -xdg_surface_ack_configure(struct xdg_surface *xdg_surface, uint32_t serial) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_surface, - XDG_SURFACE_ACK_CONFIGURE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_surface), 0, serial); -} - -#ifndef XDG_TOPLEVEL_ERROR_ENUM -#define XDG_TOPLEVEL_ERROR_ENUM -enum xdg_toplevel_error { - /** - * provided value is not a valid variant of the resize_edge enum - */ - XDG_TOPLEVEL_ERROR_INVALID_RESIZE_EDGE = 0, - /** - * invalid parent toplevel - */ - XDG_TOPLEVEL_ERROR_INVALID_PARENT = 1, - /** - * client provided an invalid min or max size - */ - XDG_TOPLEVEL_ERROR_INVALID_SIZE = 2, -}; -#endif /* XDG_TOPLEVEL_ERROR_ENUM */ - -#ifndef XDG_TOPLEVEL_RESIZE_EDGE_ENUM -#define XDG_TOPLEVEL_RESIZE_EDGE_ENUM -/** - * @ingroup iface_xdg_toplevel - * edge values for resizing - * - * These values are used to indicate which edge of a surface - * is being dragged in a resize operation. - */ -enum xdg_toplevel_resize_edge { - XDG_TOPLEVEL_RESIZE_EDGE_NONE = 0, - XDG_TOPLEVEL_RESIZE_EDGE_TOP = 1, - XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM = 2, - XDG_TOPLEVEL_RESIZE_EDGE_LEFT = 4, - XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT = 5, - XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT = 6, - XDG_TOPLEVEL_RESIZE_EDGE_RIGHT = 8, - XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT = 9, - XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT = 10, -}; -#endif /* XDG_TOPLEVEL_RESIZE_EDGE_ENUM */ - -#ifndef XDG_TOPLEVEL_STATE_ENUM -#define XDG_TOPLEVEL_STATE_ENUM -/** - * @ingroup iface_xdg_toplevel - * types of state on the surface - * - * The different state values used on the surface. This is designed for - * state values like maximized, fullscreen. It is paired with the - * configure event to ensure that both the client and the compositor - * setting the state can be synchronized. - * - * States set in this way are double-buffered, see wl_surface.commit. - */ -enum xdg_toplevel_state { - /** - * the surface is maximized - * the surface is maximized - * - * The surface is maximized. The window geometry specified in the - * configure event must be obeyed by the client, or the - * xdg_wm_base.invalid_surface_state error is raised. - * - * The client should draw without shadow or other decoration - * outside of the window geometry. - */ - XDG_TOPLEVEL_STATE_MAXIMIZED = 1, - /** - * the surface is fullscreen - * the surface is fullscreen - * - * The surface is fullscreen. The window geometry specified in - * the configure event is a maximum; the client cannot resize - * beyond it. For a surface to cover the whole fullscreened area, - * the geometry dimensions must be obeyed by the client. For more - * details, see xdg_toplevel.set_fullscreen. - */ - XDG_TOPLEVEL_STATE_FULLSCREEN = 2, - /** - * the surface is being resized - * the surface is being resized - * - * The surface is being resized. The window geometry specified in - * the configure event is a maximum; the client cannot resize - * beyond it. Clients that have aspect ratio or cell sizing - * configuration can use a smaller size, however. - */ - XDG_TOPLEVEL_STATE_RESIZING = 3, - /** - * the surface is now activated - * the surface is now activated - * - * Client window decorations should be painted as if the window - * is active. Do not assume this means that the window actually has - * keyboard or pointer focus. - */ - XDG_TOPLEVEL_STATE_ACTIVATED = 4, - /** - * the surface’s left edge is tiled - * - * The window is currently in a tiled layout and the left edge is - * considered to be adjacent to another part of the tiling grid. - * - * The client should draw without shadow or other decoration - * outside of the window geometry on the left edge. - * @since 2 - */ - XDG_TOPLEVEL_STATE_TILED_LEFT = 5, - /** - * the surface’s right edge is tiled - * - * The window is currently in a tiled layout and the right edge - * is considered to be adjacent to another part of the tiling grid. - * - * The client should draw without shadow or other decoration - * outside of the window geometry on the right edge. - * @since 2 - */ - XDG_TOPLEVEL_STATE_TILED_RIGHT = 6, - /** - * the surface’s top edge is tiled - * - * The window is currently in a tiled layout and the top edge is - * considered to be adjacent to another part of the tiling grid. - * - * The client should draw without shadow or other decoration - * outside of the window geometry on the top edge. - * @since 2 - */ - XDG_TOPLEVEL_STATE_TILED_TOP = 7, - /** - * the surface’s bottom edge is tiled - * - * The window is currently in a tiled layout and the bottom edge - * is considered to be adjacent to another part of the tiling grid. - * - * The client should draw without shadow or other decoration - * outside of the window geometry on the bottom edge. - * @since 2 - */ - XDG_TOPLEVEL_STATE_TILED_BOTTOM = 8, - /** - * surface repaint is suspended - * - * The surface is currently not ordinarily being repainted; for - * example because its content is occluded by another window, or - * its outputs are switched off due to screen locking. - * @since 6 - */ - XDG_TOPLEVEL_STATE_SUSPENDED = 9, - /** - * the surface’s left edge is constrained - * - * The left edge of the window is currently constrained, meaning - * it shouldn't attempt to resize from that edge. It can for - * example mean it's tiled next to a monitor edge on the - * constrained side of the window. - * @since 7 - */ - XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT = 10, - /** - * the surface’s right edge is constrained - * - * The right edge of the window is currently constrained, meaning - * it shouldn't attempt to resize from that edge. It can for - * example mean it's tiled next to a monitor edge on the - * constrained side of the window. - * @since 7 - */ - XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT = 11, - /** - * the surface’s top edge is constrained - * - * The top edge of the window is currently constrained, meaning - * it shouldn't attempt to resize from that edge. It can for - * example mean it's tiled next to a monitor edge on the - * constrained side of the window. - * @since 7 - */ - XDG_TOPLEVEL_STATE_CONSTRAINED_TOP = 12, - /** - * the surface’s bottom edge is tiled - * - * The bottom edge of the window is currently constrained, - * meaning it shouldn't attempt to resize from that edge. It can - * for example mean it's tiled next to a monitor edge on the - * constrained side of the window. - * @since 7 - */ - XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM = 13, -}; -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION 2 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION 2 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_TILED_TOP_SINCE_VERSION 2 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_TILED_BOTTOM_SINCE_VERSION 2 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION 6 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION 7 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT_SINCE_VERSION 7 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_CONSTRAINED_TOP_SINCE_VERSION 7 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM_SINCE_VERSION 7 -#endif /* XDG_TOPLEVEL_STATE_ENUM */ - -#ifndef XDG_TOPLEVEL_WM_CAPABILITIES_ENUM -#define XDG_TOPLEVEL_WM_CAPABILITIES_ENUM -enum xdg_toplevel_wm_capabilities { - /** - * show_window_menu is available - */ - XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU = 1, - /** - * set_maximized and unset_maximized are available - */ - XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE = 2, - /** - * set_fullscreen and unset_fullscreen are available - */ - XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN = 3, - /** - * set_minimized is available - */ - XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE = 4, -}; -#endif /* XDG_TOPLEVEL_WM_CAPABILITIES_ENUM */ - -/** - * @ingroup iface_xdg_toplevel - * @struct xdg_toplevel_listener - */ -struct xdg_toplevel_listener { - /** - * suggest a surface change - * - * This configure event asks the client to resize its toplevel - * surface or to change its state. The configured state should not - * be applied immediately. See xdg_surface.configure for details. - * - * The width and height arguments specify a hint to the window - * about how its surface should be resized in window geometry - * coordinates. See set_window_geometry. - * - * If the width or height arguments are zero, it means the client - * should decide its own window dimension. This may happen when the - * compositor needs to configure the state of the surface but - * doesn't have any information about any previous or expected - * dimension. - * - * The states listed in the event specify how the width/height - * arguments should be interpreted, and possibly how it should be - * drawn. - * - * Clients must send an ack_configure in response to this event. - * See xdg_surface.configure and xdg_surface.ack_configure for - * details. - */ - void (*configure)(void *data, - struct xdg_toplevel *xdg_toplevel, - int32_t width, - int32_t height, - struct wl_array *states); - /** - * surface wants to be closed - * - * The close event is sent by the compositor when the user wants - * the surface to be closed. This should be equivalent to the user - * clicking the close button in client-side decorations, if your - * application has any. - * - * This is only a request that the user intends to close the - * window. The client may choose to ignore this request, or show a - * dialog to ask the user to save their data, etc. - */ - void (*close)(void *data, - struct xdg_toplevel *xdg_toplevel); - /** - * recommended window geometry bounds - * - * The configure_bounds event may be sent prior to a - * xdg_toplevel.configure event to communicate the bounds a window - * geometry size is recommended to constrain to. - * - * The passed width and height are in surface coordinate space. If - * width and height are 0, it means bounds is unknown and - * equivalent to as if no configure_bounds event was ever sent for - * this surface. - * - * The bounds can for example correspond to the size of a monitor - * excluding any panels or other shell components, so that a - * surface isn't created in a way that it cannot fit. - * - * The bounds may change at any point, and in such a case, a new - * xdg_toplevel.configure_bounds will be sent, followed by - * xdg_toplevel.configure and xdg_surface.configure. - * @since 4 - */ - void (*configure_bounds)(void *data, - struct xdg_toplevel *xdg_toplevel, - int32_t width, - int32_t height); - /** - * compositor capabilities - * - * This event advertises the capabilities supported by the - * compositor. If a capability isn't supported, clients should hide - * or disable the UI elements that expose this functionality. For - * instance, if the compositor doesn't advertise support for - * minimized toplevels, a button triggering the set_minimized - * request should not be displayed. - * - * The compositor will ignore requests it doesn't support. For - * instance, a compositor which doesn't advertise support for - * minimized will ignore set_minimized requests. - * - * Compositors must send this event once before the first - * xdg_surface.configure event. When the capabilities change, - * compositors must send this event again and then send an - * xdg_surface.configure event. - * - * The configured state should not be applied immediately. See - * xdg_surface.configure for details. - * - * The capabilities are sent as an array of 32-bit unsigned - * integers in native endianness. - * @param capabilities array of 32-bit capabilities - * @since 5 - */ - void (*wm_capabilities)(void *data, - struct xdg_toplevel *xdg_toplevel, - struct wl_array *capabilities); -}; - -/** - * @ingroup iface_xdg_toplevel - */ -static inline int -xdg_toplevel_add_listener(struct xdg_toplevel *xdg_toplevel, - const struct xdg_toplevel_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) xdg_toplevel, - (void (**)(void)) listener, data); -} - -#define XDG_TOPLEVEL_DESTROY 0 -#define XDG_TOPLEVEL_SET_PARENT 1 -#define XDG_TOPLEVEL_SET_TITLE 2 -#define XDG_TOPLEVEL_SET_APP_ID 3 -#define XDG_TOPLEVEL_SHOW_WINDOW_MENU 4 -#define XDG_TOPLEVEL_MOVE 5 -#define XDG_TOPLEVEL_RESIZE 6 -#define XDG_TOPLEVEL_SET_MAX_SIZE 7 -#define XDG_TOPLEVEL_SET_MIN_SIZE 8 -#define XDG_TOPLEVEL_SET_MAXIMIZED 9 -#define XDG_TOPLEVEL_UNSET_MAXIMIZED 10 -#define XDG_TOPLEVEL_SET_FULLSCREEN 11 -#define XDG_TOPLEVEL_UNSET_FULLSCREEN 12 -#define XDG_TOPLEVEL_SET_MINIMIZED 13 - -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_CONFIGURE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_CLOSE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION 4 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION 5 - -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_PARENT_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_TITLE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_APP_ID_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SHOW_WINDOW_MENU_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_MOVE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_RESIZE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_MAX_SIZE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_MIN_SIZE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_MAXIMIZED_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_UNSET_MAXIMIZED_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_FULLSCREEN_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_UNSET_FULLSCREEN_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_toplevel - */ -#define XDG_TOPLEVEL_SET_MINIMIZED_SINCE_VERSION 1 - -/** @ingroup iface_xdg_toplevel */ -static inline void -xdg_toplevel_set_user_data(struct xdg_toplevel *xdg_toplevel, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) xdg_toplevel, user_data); -} - -/** @ingroup iface_xdg_toplevel */ -static inline void * -xdg_toplevel_get_user_data(struct xdg_toplevel *xdg_toplevel) -{ - return wl_proxy_get_user_data((struct wl_proxy *) xdg_toplevel); -} - -static inline uint32_t -xdg_toplevel_get_version(struct xdg_toplevel *xdg_toplevel) -{ - return wl_proxy_get_version((struct wl_proxy *) xdg_toplevel); -} - -/** - * @ingroup iface_xdg_toplevel - * - * This request destroys the role surface and unmaps the surface; - * see "Unmapping" behavior in interface section for details. - */ -static inline void -xdg_toplevel_destroy(struct xdg_toplevel *xdg_toplevel) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Set the "parent" of this surface. This surface should be stacked - * above the parent surface and all other ancestor surfaces. - * - * Parent surfaces should be set on dialogs, toolboxes, or other - * "auxiliary" surfaces, so that the parent is raised when the dialog - * is raised. - * - * Setting a null parent for a child surface unsets its parent. Setting - * a null parent for a surface which currently has no parent is a no-op. - * - * Only mapped surfaces can have child surfaces. Setting a parent which - * is not mapped is equivalent to setting a null parent. If a surface - * becomes unmapped, its children's parent is set to the parent of - * the now-unmapped surface. If the now-unmapped surface has no parent, - * its children's parent is unset. If the now-unmapped surface becomes - * mapped again, its parent-child relationship is not restored. - * - * The parent toplevel must not be one of the child toplevel's - * descendants, and the parent must be different from the child toplevel, - * otherwise the invalid_parent protocol error is raised. - */ -static inline void -xdg_toplevel_set_parent(struct xdg_toplevel *xdg_toplevel, struct xdg_toplevel *parent) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_SET_PARENT, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, parent); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Set a short title for the surface. - * - * This string may be used to identify the surface in a task bar, - * window list, or other user interface elements provided by the - * compositor. - * - * The string must be encoded in UTF-8. - */ -static inline void -xdg_toplevel_set_title(struct xdg_toplevel *xdg_toplevel, const char *title) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_SET_TITLE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, title); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Set an application identifier for the surface. - * - * The app ID identifies the general class of applications to which - * the surface belongs. The compositor can use this to group multiple - * surfaces together, or to determine how to launch a new application. - * - * For D-Bus activatable applications, the app ID is used as the D-Bus - * service name. - * - * The compositor shell will try to group application surfaces together - * by their app ID. As a best practice, it is suggested to select app - * ID's that match the basename of the application's .desktop file. - * For example, "org.freedesktop.FooViewer" where the .desktop file is - * "org.freedesktop.FooViewer.desktop". - * - * Like other properties, a set_app_id request can be sent after the - * xdg_toplevel has been mapped to update the property. - * - * See the desktop-entry specification [0] for more details on - * application identifiers and how they relate to well-known D-Bus - * names and .desktop files. - * - * [0] https://standards.freedesktop.org/desktop-entry-spec/ - */ -static inline void -xdg_toplevel_set_app_id(struct xdg_toplevel *xdg_toplevel, const char *app_id) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_SET_APP_ID, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, app_id); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Clients implementing client-side decorations might want to show - * a context menu when right-clicking on the decorations, giving the - * user a menu that they can use to maximize or minimize the window. - * - * This request asks the compositor to pop up such a window menu at - * the given position, relative to the local surface coordinates of - * the parent surface. There are no guarantees as to what menu items - * the window menu contains, or even if a window menu will be drawn - * at all. - * - * This request must be used in response to some sort of user action - * like a button press, key press, or touch down event. - */ -static inline void -xdg_toplevel_show_window_menu(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial, int32_t x, int32_t y) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_SHOW_WINDOW_MENU, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial, x, y); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Start an interactive, user-driven move of the surface. - * - * This request must be used in response to some sort of user action - * like a button press, key press, or touch down event. The passed - * serial is used to determine the type of interactive move (touch, - * pointer, etc). - * - * The server may ignore move requests depending on the state of - * the surface (e.g. fullscreen or maximized), or if the passed serial - * is no longer valid. - * - * If triggered, the surface will lose the focus of the device - * (wl_pointer, wl_touch, etc) used for the move. It is up to the - * compositor to visually indicate that the move is taking place, such as - * updating a pointer cursor, during the move. There is no guarantee - * that the device focus will return when the move is completed. - */ -static inline void -xdg_toplevel_move(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_MOVE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Start a user-driven, interactive resize of the surface. - * - * This request must be used in response to some sort of user action - * like a button press, key press, or touch down event. The passed - * serial is used to determine the type of interactive resize (touch, - * pointer, etc). - * - * The server may ignore resize requests depending on the state of - * the surface (e.g. fullscreen or maximized). - * - * If triggered, the client will receive configure events with the - * "resize" state enum value and the expected sizes. See the "resize" - * enum value for more details about what is required. The client - * must also acknowledge configure events using "ack_configure". After - * the resize is completed, the client will receive another "configure" - * event without the resize state. - * - * If triggered, the surface also will lose the focus of the device - * (wl_pointer, wl_touch, etc) used for the resize. It is up to the - * compositor to visually indicate that the resize is taking place, - * such as updating a pointer cursor, during the resize. There is no - * guarantee that the device focus will return when the resize is - * completed. - * - * The edges parameter specifies how the surface should be resized, and - * is one of the values of the resize_edge enum. Values not matching - * a variant of the enum will cause the invalid_resize_edge protocol error. - * The compositor may use this information to update the surface position - * for example when dragging the top left corner. The compositor may also - * use this information to adapt its behavior, e.g. choose an appropriate - * cursor image. - */ -static inline void -xdg_toplevel_resize(struct xdg_toplevel *xdg_toplevel, struct wl_seat *seat, uint32_t serial, uint32_t edges) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_RESIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, seat, serial, edges); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Set a maximum size for the window. - * - * The client can specify a maximum size so that the compositor does - * not try to configure the window beyond this size. - * - * The width and height arguments are in window geometry coordinates. - * See xdg_surface.set_window_geometry. - * - * Values set in this way are double-buffered, see wl_surface.commit. - * - * The compositor can use this information to allow or disallow - * different states like maximize or fullscreen and draw accurate - * animations. - * - * Similarly, a tiling window manager may use this information to - * place and resize client windows in a more effective way. - * - * The client should not rely on the compositor to obey the maximum - * size. The compositor may decide to ignore the values set by the - * client and request a larger size. - * - * If never set, or a value of zero in the request, means that the - * client has no expected maximum size in the given dimension. - * As a result, a client wishing to reset the maximum size - * to an unspecified state can use zero for width and height in the - * request. - * - * Requesting a maximum size to be smaller than the minimum size of - * a surface is illegal and will result in an invalid_size error. - * - * The width and height must be greater than or equal to zero. Using - * strictly negative values for width or height will result in a - * invalid_size error. - */ -static inline void -xdg_toplevel_set_max_size(struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_SET_MAX_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, width, height); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Set a minimum size for the window. - * - * The client can specify a minimum size so that the compositor does - * not try to configure the window below this size. - * - * The width and height arguments are in window geometry coordinates. - * See xdg_surface.set_window_geometry. - * - * Values set in this way are double-buffered, see wl_surface.commit. - * - * The compositor can use this information to allow or disallow - * different states like maximize or fullscreen and draw accurate - * animations. - * - * Similarly, a tiling window manager may use this information to - * place and resize client windows in a more effective way. - * - * The client should not rely on the compositor to obey the minimum - * size. The compositor may decide to ignore the values set by the - * client and request a smaller size. - * - * If never set, or a value of zero in the request, means that the - * client has no expected minimum size in the given dimension. - * As a result, a client wishing to reset the minimum size - * to an unspecified state can use zero for width and height in the - * request. - * - * Requesting a minimum size to be larger than the maximum size of - * a surface is illegal and will result in an invalid_size error. - * - * The width and height must be greater than or equal to zero. Using - * strictly negative values for width and height will result in a - * invalid_size error. - */ -static inline void -xdg_toplevel_set_min_size(struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_SET_MIN_SIZE, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, width, height); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Maximize the surface. - * - * After requesting that the surface should be maximized, the compositor - * will respond by emitting a configure event. Whether this configure - * actually sets the window maximized is subject to compositor policies. - * The client must then update its content, drawing in the configured - * state. The client must also acknowledge the configure when committing - * the new content (see ack_configure). - * - * It is up to the compositor to decide how and where to maximize the - * surface, for example which output and what region of the screen should - * be used. - * - * If the surface was already maximized, the compositor will still emit - * a configure event with the "maximized" state. - * - * If the surface is in a fullscreen state, this request has no direct - * effect. It may alter the state the surface is returned to when - * unmaximized unless overridden by the compositor. - */ -static inline void -xdg_toplevel_set_maximized(struct xdg_toplevel *xdg_toplevel) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_SET_MAXIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Unmaximize the surface. - * - * After requesting that the surface should be unmaximized, the compositor - * will respond by emitting a configure event. Whether this actually - * un-maximizes the window is subject to compositor policies. - * If available and applicable, the compositor will include the window - * geometry dimensions the window had prior to being maximized in the - * configure event. The client must then update its content, drawing it in - * the configured state. The client must also acknowledge the configure - * when committing the new content (see ack_configure). - * - * It is up to the compositor to position the surface after it was - * unmaximized; usually the position the surface had before maximizing, if - * applicable. - * - * If the surface was already not maximized, the compositor will still - * emit a configure event without the "maximized" state. - * - * If the surface is in a fullscreen state, this request has no direct - * effect. It may alter the state the surface is returned to when - * unmaximized unless overridden by the compositor. - */ -static inline void -xdg_toplevel_unset_maximized(struct xdg_toplevel *xdg_toplevel) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_UNSET_MAXIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Make the surface fullscreen. - * - * After requesting that the surface should be fullscreened, the - * compositor will respond by emitting a configure event. Whether the - * client is actually put into a fullscreen state is subject to compositor - * policies. The client must also acknowledge the configure when - * committing the new content (see ack_configure). - * - * The output passed by the request indicates the client's preference as - * to which display it should be set fullscreen on. If this value is NULL, - * it's up to the compositor to choose which display will be used to map - * this surface. - * - * If the surface doesn't cover the whole output, the compositor will - * position the surface in the center of the output and compensate with - * with border fill covering the rest of the output. The content of the - * border fill is undefined, but should be assumed to be in some way that - * attempts to blend into the surrounding area (e.g. solid black). - * - * If the fullscreened surface is not opaque, the compositor must make - * sure that other screen content not part of the same surface tree (made - * up of subsurfaces, popups or similarly coupled surfaces) are not - * visible below the fullscreened surface. - */ -static inline void -xdg_toplevel_set_fullscreen(struct xdg_toplevel *xdg_toplevel, struct wl_output *output) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_SET_FULLSCREEN, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0, output); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Make the surface no longer fullscreen. - * - * After requesting that the surface should be unfullscreened, the - * compositor will respond by emitting a configure event. - * Whether this actually removes the fullscreen state of the client is - * subject to compositor policies. - * - * Making a surface unfullscreen sets states for the surface based on the following: - * * the state(s) it may have had before becoming fullscreen - * * any state(s) decided by the compositor - * * any state(s) requested by the client while the surface was fullscreen - * - * The compositor may include the previous window geometry dimensions in - * the configure event, if applicable. - * - * The client must also acknowledge the configure when committing the new - * content (see ack_configure). - */ -static inline void -xdg_toplevel_unset_fullscreen(struct xdg_toplevel *xdg_toplevel) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_UNSET_FULLSCREEN, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0); -} - -/** - * @ingroup iface_xdg_toplevel - * - * Request that the compositor minimize your surface. There is no - * way to know if the surface is currently minimized, nor is there - * any way to unset minimization on this surface. - * - * If you are looking to throttle redrawing when minimized, please - * instead use the wl_surface.frame event for this, as this will - * also work with live previews on windows in Alt-Tab, Expose or - * similar compositor features. - */ -static inline void -xdg_toplevel_set_minimized(struct xdg_toplevel *xdg_toplevel) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_toplevel, - XDG_TOPLEVEL_SET_MINIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_toplevel), 0); -} - -#ifndef XDG_POPUP_ERROR_ENUM -#define XDG_POPUP_ERROR_ENUM -enum xdg_popup_error { - /** - * tried to grab after being mapped - */ - XDG_POPUP_ERROR_INVALID_GRAB = 0, -}; -#endif /* XDG_POPUP_ERROR_ENUM */ - -/** - * @ingroup iface_xdg_popup - * @struct xdg_popup_listener - */ -struct xdg_popup_listener { - /** - * configure the popup surface - * - * This event asks the popup surface to configure itself given - * the configuration. The configured state should not be applied - * immediately. See xdg_surface.configure for details. - * - * The x and y arguments represent the position the popup was - * placed at given the xdg_positioner rule, relative to the upper - * left corner of the window geometry of the parent surface. - * - * For version 2 or older, the configure event for an xdg_popup is - * only ever sent once for the initial configuration. Starting with - * version 3, it may be sent again if the popup is setup with an - * xdg_positioner with set_reactive requested, or in response to - * xdg_popup.reposition requests. - * @param x x position relative to parent surface window geometry - * @param y y position relative to parent surface window geometry - * @param width window geometry width - * @param height window geometry height - */ - void (*configure)(void *data, - struct xdg_popup *xdg_popup, - int32_t x, - int32_t y, - int32_t width, - int32_t height); - /** - * popup interaction is done - * - * The popup_done event is sent out when a popup is dismissed by - * the compositor. The client should destroy the xdg_popup object - * at this point. - */ - void (*popup_done)(void *data, - struct xdg_popup *xdg_popup); - /** - * signal the completion of a repositioned request - * - * The repositioned event is sent as part of a popup - * configuration sequence, together with xdg_popup.configure and - * lastly xdg_surface.configure to notify the completion of a - * reposition request. - * - * The repositioned event is to notify about the completion of a - * xdg_popup.reposition request. The token argument is the token - * passed in the xdg_popup.reposition request. - * - * Immediately after this event is emitted, xdg_popup.configure and - * xdg_surface.configure will be sent with the updated size and - * position, as well as a new configure serial. - * - * The client should optionally update the content of the popup, - * but must acknowledge the new popup configuration for the new - * position to take effect. See xdg_surface.ack_configure for - * details. - * @param token reposition request token - * @since 3 - */ - void (*repositioned)(void *data, - struct xdg_popup *xdg_popup, - uint32_t token); -}; - -/** - * @ingroup iface_xdg_popup - */ -static inline int -xdg_popup_add_listener(struct xdg_popup *xdg_popup, - const struct xdg_popup_listener *listener, void *data) -{ - return wl_proxy_add_listener((struct wl_proxy *) xdg_popup, - (void (**)(void)) listener, data); -} - -#define XDG_POPUP_DESTROY 0 -#define XDG_POPUP_GRAB 1 -#define XDG_POPUP_REPOSITION 2 - -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_CONFIGURE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_POPUP_DONE_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_REPOSITIONED_SINCE_VERSION 3 - -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_DESTROY_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_GRAB_SINCE_VERSION 1 -/** - * @ingroup iface_xdg_popup - */ -#define XDG_POPUP_REPOSITION_SINCE_VERSION 3 - -/** @ingroup iface_xdg_popup */ -static inline void -xdg_popup_set_user_data(struct xdg_popup *xdg_popup, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) xdg_popup, user_data); -} - -/** @ingroup iface_xdg_popup */ -static inline void * -xdg_popup_get_user_data(struct xdg_popup *xdg_popup) -{ - return wl_proxy_get_user_data((struct wl_proxy *) xdg_popup); -} - -static inline uint32_t -xdg_popup_get_version(struct xdg_popup *xdg_popup) -{ - return wl_proxy_get_version((struct wl_proxy *) xdg_popup); -} - -/** - * @ingroup iface_xdg_popup - * - * This destroys the popup. Explicitly destroying the xdg_popup - * object will also dismiss the popup, and unmap the surface. - * - * If this xdg_popup is not the "topmost" popup, the - * xdg_wm_base.not_the_topmost_popup protocol error will be sent. - */ -static inline void -xdg_popup_destroy(struct xdg_popup *xdg_popup) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup, - XDG_POPUP_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), WL_MARSHAL_FLAG_DESTROY); -} - -/** - * @ingroup iface_xdg_popup - * - * This request makes the created popup take an explicit grab. An explicit - * grab will be dismissed when the user dismisses the popup, or when the - * client destroys the xdg_popup. This can be done by the user clicking - * outside the surface, using the keyboard, or even locking the screen - * through closing the lid or a timeout. - * - * If the compositor denies the grab, the popup will be immediately - * dismissed. - * - * This request must be used in response to some sort of user action like a - * button press, key press, or touch down event. The serial number of the - * event should be passed as 'serial'. - * - * The parent of a grabbing popup must either be an xdg_toplevel surface or - * another xdg_popup with an explicit grab. If the parent is another - * xdg_popup it means that the popups are nested, with this popup now being - * the topmost popup. - * - * Nested popups must be destroyed in the reverse order they were created - * in, e.g. the only popup you are allowed to destroy at all times is the - * topmost one. - * - * When compositors choose to dismiss a popup, they may dismiss every - * nested grabbing popup as well. When a compositor dismisses popups, it - * will follow the same dismissing order as required from the client. - * - * If the topmost grabbing popup is destroyed, the grab will be returned to - * the parent of the popup, if that parent previously had an explicit grab. - * - * If the parent is a grabbing popup which has already been dismissed, this - * popup will be immediately dismissed. If the parent is a popup that did - * not take an explicit grab, an error will be raised. - * - * During a popup grab, the client owning the grab will receive pointer - * and touch events for all their surfaces as normal (similar to an - * "owner-events" grab in X11 parlance), while the top most grabbing popup - * will always have keyboard focus. - */ -static inline void -xdg_popup_grab(struct xdg_popup *xdg_popup, struct wl_seat *seat, uint32_t serial) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup, - XDG_POPUP_GRAB, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), 0, seat, serial); -} - -/** - * @ingroup iface_xdg_popup - * - * Reposition an already-mapped popup. The popup will be placed given the - * details in the passed xdg_positioner object, and a - * xdg_popup.repositioned followed by xdg_popup.configure and - * xdg_surface.configure will be emitted in response. Any parameters set - * by the previous positioner will be discarded. - * - * The passed token will be sent in the corresponding - * xdg_popup.repositioned event. The new popup position will not take - * effect until the corresponding configure event is acknowledged by the - * client. See xdg_popup.repositioned for details. The token itself is - * opaque, and has no other special meaning. - * - * If multiple reposition requests are sent, the compositor may skip all - * but the last one. - * - * If the popup is repositioned in response to a configure event for its - * parent, the client should send an xdg_positioner.set_parent_configure - * and possibly an xdg_positioner.set_parent_size request to allow the - * compositor to properly constrain the popup. - * - * If the popup is repositioned together with a parent that is being - * resized, but not in response to a configure event, the client should - * send an xdg_positioner.set_parent_size request. - */ -static inline void -xdg_popup_reposition(struct xdg_popup *xdg_popup, struct xdg_positioner *positioner, uint32_t token) -{ - wl_proxy_marshal_flags((struct wl_proxy *) xdg_popup, - XDG_POPUP_REPOSITION, NULL, wl_proxy_get_version((struct wl_proxy *) xdg_popup), 0, positioner, token); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/driver/wayland-protocols/xdg-shell-v1-protocol.c b/driver/wayland-protocols/xdg-shell-v1-protocol.c deleted file mode 100644 index 4faed8df2..000000000 --- a/driver/wayland-protocols/xdg-shell-v1-protocol.c +++ /dev/null @@ -1,184 +0,0 @@ -/* Generated by wayland-scanner 1.23.1 */ - -/* - * Copyright © 2008-2013 Kristian Høgsberg - * Copyright © 2013 Rafael Antognolli - * Copyright © 2013 Jasper St. Pierre - * Copyright © 2010-2013 Intel Corporation - * Copyright © 2015-2017 Samsung Electronics Co., Ltd - * Copyright © 2015-2017 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include "wayland-util.h" - -#ifndef __has_attribute -# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ -#endif - -#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) -#define WL_PRIVATE __attribute__ ((visibility("hidden"))) -#else -#define WL_PRIVATE -#endif - -extern const struct wl_interface wl_output_interface; -extern const struct wl_interface wl_seat_interface; -extern const struct wl_interface wl_surface_interface; -extern const struct wl_interface xdg_popup_interface; -extern const struct wl_interface xdg_positioner_interface; -extern const struct wl_interface xdg_surface_interface; -extern const struct wl_interface xdg_toplevel_interface; - -static const struct wl_interface *xdg_shell_types[] = { - NULL, - NULL, - NULL, - NULL, - &xdg_positioner_interface, - &xdg_surface_interface, - &wl_surface_interface, - &xdg_toplevel_interface, - &xdg_popup_interface, - &xdg_surface_interface, - &xdg_positioner_interface, - &xdg_toplevel_interface, - &wl_seat_interface, - NULL, - NULL, - NULL, - &wl_seat_interface, - NULL, - &wl_seat_interface, - NULL, - NULL, - &wl_output_interface, - &wl_seat_interface, - NULL, - &xdg_positioner_interface, - NULL, -}; - -static const struct wl_message xdg_wm_base_requests[] = { - { "destroy", "", xdg_shell_types + 0 }, - { "create_positioner", "n", xdg_shell_types + 4 }, - { "get_xdg_surface", "no", xdg_shell_types + 5 }, - { "pong", "u", xdg_shell_types + 0 }, -}; - -static const struct wl_message xdg_wm_base_events[] = { - { "ping", "u", xdg_shell_types + 0 }, -}; - -WL_PRIVATE const struct wl_interface xdg_wm_base_interface = { - "xdg_wm_base", 7, - 4, xdg_wm_base_requests, - 1, xdg_wm_base_events, -}; - -static const struct wl_message xdg_positioner_requests[] = { - { "destroy", "", xdg_shell_types + 0 }, - { "set_size", "ii", xdg_shell_types + 0 }, - { "set_anchor_rect", "iiii", xdg_shell_types + 0 }, - { "set_anchor", "u", xdg_shell_types + 0 }, - { "set_gravity", "u", xdg_shell_types + 0 }, - { "set_constraint_adjustment", "u", xdg_shell_types + 0 }, - { "set_offset", "ii", xdg_shell_types + 0 }, - { "set_reactive", "3", xdg_shell_types + 0 }, - { "set_parent_size", "3ii", xdg_shell_types + 0 }, - { "set_parent_configure", "3u", xdg_shell_types + 0 }, -}; - -WL_PRIVATE const struct wl_interface xdg_positioner_interface = { - "xdg_positioner", 7, - 10, xdg_positioner_requests, - 0, NULL, -}; - -static const struct wl_message xdg_surface_requests[] = { - { "destroy", "", xdg_shell_types + 0 }, - { "get_toplevel", "n", xdg_shell_types + 7 }, - { "get_popup", "n?oo", xdg_shell_types + 8 }, - { "set_window_geometry", "iiii", xdg_shell_types + 0 }, - { "ack_configure", "u", xdg_shell_types + 0 }, -}; - -static const struct wl_message xdg_surface_events[] = { - { "configure", "u", xdg_shell_types + 0 }, -}; - -WL_PRIVATE const struct wl_interface xdg_surface_interface = { - "xdg_surface", 7, - 5, xdg_surface_requests, - 1, xdg_surface_events, -}; - -static const struct wl_message xdg_toplevel_requests[] = { - { "destroy", "", xdg_shell_types + 0 }, - { "set_parent", "?o", xdg_shell_types + 11 }, - { "set_title", "s", xdg_shell_types + 0 }, - { "set_app_id", "s", xdg_shell_types + 0 }, - { "show_window_menu", "ouii", xdg_shell_types + 12 }, - { "move", "ou", xdg_shell_types + 16 }, - { "resize", "ouu", xdg_shell_types + 18 }, - { "set_max_size", "ii", xdg_shell_types + 0 }, - { "set_min_size", "ii", xdg_shell_types + 0 }, - { "set_maximized", "", xdg_shell_types + 0 }, - { "unset_maximized", "", xdg_shell_types + 0 }, - { "set_fullscreen", "?o", xdg_shell_types + 21 }, - { "unset_fullscreen", "", xdg_shell_types + 0 }, - { "set_minimized", "", xdg_shell_types + 0 }, -}; - -static const struct wl_message xdg_toplevel_events[] = { - { "configure", "iia", xdg_shell_types + 0 }, - { "close", "", xdg_shell_types + 0 }, - { "configure_bounds", "4ii", xdg_shell_types + 0 }, - { "wm_capabilities", "5a", xdg_shell_types + 0 }, -}; - -WL_PRIVATE const struct wl_interface xdg_toplevel_interface = { - "xdg_toplevel", 7, - 14, xdg_toplevel_requests, - 4, xdg_toplevel_events, -}; - -static const struct wl_message xdg_popup_requests[] = { - { "destroy", "", xdg_shell_types + 0 }, - { "grab", "ou", xdg_shell_types + 22 }, - { "reposition", "3ou", xdg_shell_types + 24 }, -}; - -static const struct wl_message xdg_popup_events[] = { - { "configure", "iiii", xdg_shell_types + 0 }, - { "popup_done", "", xdg_shell_types + 0 }, - { "repositioned", "3u", xdg_shell_types + 0 }, -}; - -WL_PRIVATE const struct wl_interface xdg_popup_interface = { - "xdg_popup", 7, - 3, xdg_popup_requests, - 3, xdg_popup_events, -}; - diff --git a/driver/wayland-protocols/xdg-shell.xml b/driver/wayland-protocols/xdg-shell.xml deleted file mode 100644 index c4d4685a3..000000000 --- a/driver/wayland-protocols/xdg-shell.xml +++ /dev/null @@ -1,1415 +0,0 @@ - - - - - Copyright © 2008-2013 Kristian Høgsberg - Copyright © 2013 Rafael Antognolli - Copyright © 2013 Jasper St. Pierre - Copyright © 2010-2013 Intel Corporation - Copyright © 2015-2017 Samsung Electronics Co., Ltd - Copyright © 2015-2017 Red Hat Inc. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - - - - The xdg_wm_base interface is exposed as a global object enabling clients - to turn their wl_surfaces into windows in a desktop environment. It - defines the basic functionality needed for clients and the compositor to - create windows that can be dragged, resized, maximized, etc, as well as - creating transient windows such as popup menus. - - - - - - - - - - - - - - - Destroy this xdg_wm_base object. - - Destroying a bound xdg_wm_base object while there are surfaces - still alive created by this xdg_wm_base object instance is illegal - and will result in a defunct_surfaces error. - - - - - - Create a positioner object. A positioner object is used to position - surfaces relative to some parent surface. See the interface description - and xdg_surface.get_popup for details. - - - - - - - This creates an xdg_surface for the given surface. While xdg_surface - itself is not a role, the corresponding surface may only be assigned - a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is - illegal to create an xdg_surface for a wl_surface which already has an - assigned role and this will result in a role error. - - This creates an xdg_surface for the given surface. An xdg_surface is - used as basis to define a role to a given surface, such as xdg_toplevel - or xdg_popup. It also manages functionality shared between xdg_surface - based surface roles. - - See the documentation of xdg_surface for more details about what an - xdg_surface is and how it is used. - - - - - - - - A client must respond to a ping event with a pong request or - the client may be deemed unresponsive. See xdg_wm_base.ping - and xdg_wm_base.error.unresponsive. - - - - - - - The ping event asks the client if it's still alive. Pass the - serial specified in the event back to the compositor by sending - a "pong" request back with the specified serial. See xdg_wm_base.pong. - - Compositors can use this to determine if the client is still - alive. It's unspecified what will happen if the client doesn't - respond to the ping request, or in what timeframe. Clients should - try to respond in a reasonable amount of time. The “unresponsive” - error is provided for compositors that wish to disconnect unresponsive - clients. - - A compositor is free to ping in any way it wants, but a client must - always respond to any xdg_wm_base object it created. - - - - - - - - The xdg_positioner provides a collection of rules for the placement of a - child surface relative to a parent surface. Rules can be defined to ensure - the child surface remains within the visible area's borders, and to - specify how the child surface changes its position, such as sliding along - an axis, or flipping around a rectangle. These positioner-created rules are - constrained by the requirement that a child surface must intersect with or - be at least partially adjacent to its parent surface. - - See the various requests for details about possible rules. - - At the time of the request, the compositor makes a copy of the rules - specified by the xdg_positioner. Thus, after the request is complete the - xdg_positioner object can be destroyed or reused; further changes to the - object will have no effect on previous usages. - - For an xdg_positioner object to be considered complete, it must have a - non-zero size set by set_size, and a non-zero anchor rectangle set by - set_anchor_rect. Passing an incomplete xdg_positioner object when - positioning a surface raises an invalid_positioner error. - - - - - - - - - Notify the compositor that the xdg_positioner will no longer be used. - - - - - - Set the size of the surface that is to be positioned with the positioner - object. The size is in surface-local coordinates and corresponds to the - window geometry. See xdg_surface.set_window_geometry. - - If a zero or negative size is set the invalid_input error is raised. - - - - - - - - Specify the anchor rectangle within the parent surface that the child - surface will be placed relative to. The rectangle is relative to the - window geometry as defined by xdg_surface.set_window_geometry of the - parent surface. - - When the xdg_positioner object is used to position a child surface, the - anchor rectangle may not extend outside the window geometry of the - positioned child's parent surface. - - If a negative size is set the invalid_input error is raised. - - - - - - - - - - - - - - - - - - - - - - Defines the anchor point for the anchor rectangle. The specified anchor - is used derive an anchor point that the child surface will be - positioned relative to. If a corner anchor is set (e.g. 'top_left' or - 'bottom_right'), the anchor point will be at the specified corner; - otherwise, the derived anchor point will be centered on the specified - edge, or in the center of the anchor rectangle if no edge is specified. - - - - - - - - - - - - - - - - - - - Defines in what direction a surface should be positioned, relative to - the anchor point of the parent surface. If a corner gravity is - specified (e.g. 'bottom_right' or 'top_left'), then the child surface - will be placed towards the specified gravity; otherwise, the child - surface will be centered over the anchor point on any axis that had no - gravity specified. If the gravity is not in the ‘gravity’ enum, an - invalid_input error is raised. - - - - - - - The constraint adjustment value define ways the compositor will adjust - the position of the surface, if the unadjusted position would result - in the surface being partly constrained. - - Whether a surface is considered 'constrained' is left to the compositor - to determine. For example, the surface may be partly outside the - compositor's defined 'work area', thus necessitating the child surface's - position be adjusted until it is entirely inside the work area. - - The adjustments can be combined, according to a defined precedence: 1) - Flip, 2) Slide, 3) Resize. - - - - Don't alter the surface position even if it is constrained on some - axis, for example partially outside the edge of an output. - - - - - Slide the surface along the x axis until it is no longer constrained. - - First try to slide towards the direction of the gravity on the x axis - until either the edge in the opposite direction of the gravity is - unconstrained or the edge in the direction of the gravity is - constrained. - - Then try to slide towards the opposite direction of the gravity on the - x axis until either the edge in the direction of the gravity is - unconstrained or the edge in the opposite direction of the gravity is - constrained. - - - - - Slide the surface along the y axis until it is no longer constrained. - - First try to slide towards the direction of the gravity on the y axis - until either the edge in the opposite direction of the gravity is - unconstrained or the edge in the direction of the gravity is - constrained. - - Then try to slide towards the opposite direction of the gravity on the - y axis until either the edge in the direction of the gravity is - unconstrained or the edge in the opposite direction of the gravity is - constrained. - - - - - Invert the anchor and gravity on the x axis if the surface is - constrained on the x axis. For example, if the left edge of the - surface is constrained, the gravity is 'left' and the anchor is - 'left', change the gravity to 'right' and the anchor to 'right'. - - If the adjusted position also ends up being constrained, the resulting - position of the flip_x adjustment will be the one before the - adjustment. - - - - - Invert the anchor and gravity on the y axis if the surface is - constrained on the y axis. For example, if the bottom edge of the - surface is constrained, the gravity is 'bottom' and the anchor is - 'bottom', change the gravity to 'top' and the anchor to 'top'. - - The adjusted position is calculated given the original anchor - rectangle and offset, but with the new flipped anchor and gravity - values. - - If the adjusted position also ends up being constrained, the resulting - position of the flip_y adjustment will be the one before the - adjustment. - - - - - Resize the surface horizontally so that it is completely - unconstrained. - - - - - Resize the surface vertically so that it is completely unconstrained. - - - - - - - Specify how the window should be positioned if the originally intended - position caused the surface to be constrained, meaning at least - partially outside positioning boundaries set by the compositor. The - adjustment is set by constructing a bitmask describing the adjustment to - be made when the surface is constrained on that axis. - - If no bit for one axis is set, the compositor will assume that the child - surface should not change its position on that axis when constrained. - - If more than one bit for one axis is set, the order of how adjustments - are applied is specified in the corresponding adjustment descriptions. - - The default adjustment is none. - - - - - - - Specify the surface position offset relative to the position of the - anchor on the anchor rectangle and the anchor on the surface. For - example if the anchor of the anchor rectangle is at (x, y), the surface - has the gravity bottom|right, and the offset is (ox, oy), the calculated - surface position will be (x + ox, y + oy). The offset position of the - surface is the one used for constraint testing. See - set_constraint_adjustment. - - An example use case is placing a popup menu on top of a user interface - element, while aligning the user interface element of the parent surface - with some user interface element placed somewhere in the popup surface. - - - - - - - - - - When set reactive, the surface is reconstrained if the conditions used - for constraining changed, e.g. the parent window moved. - - If the conditions changed and the popup was reconstrained, an - xdg_popup.configure event is sent with updated geometry, followed by an - xdg_surface.configure event. - - - - - - Set the parent window geometry the compositor should use when - positioning the popup. The compositor may use this information to - determine the future state the popup should be constrained using. If - this doesn't match the dimension of the parent the popup is eventually - positioned against, the behavior is undefined. - - The arguments are given in the surface-local coordinate space. - - - - - - - - Set the serial of an xdg_surface.configure event this positioner will be - used in response to. The compositor may use this information together - with set_parent_size to determine what future state the popup should be - constrained using. - - - - - - - - An interface that may be implemented by a wl_surface, for - implementations that provide a desktop-style user interface. - - It provides a base set of functionality required to construct user - interface elements requiring management by the compositor, such as - toplevel windows, menus, etc. The types of functionality are split into - xdg_surface roles. - - Creating an xdg_surface does not set the role for a wl_surface. In order - to map an xdg_surface, the client must create a role-specific object - using, e.g., get_toplevel, get_popup. The wl_surface for any given - xdg_surface can have at most one role, and may not be assigned any role - not based on xdg_surface. - - A role must be assigned before any other requests are made to the - xdg_surface object. - - The client must call wl_surface.commit on the corresponding wl_surface - for the xdg_surface state to take effect. - - Creating an xdg_surface from a wl_surface which has a buffer attached or - committed is a client error, and any attempts by a client to attach or - manipulate a buffer prior to the first xdg_surface.configure call must - also be treated as errors. - - After creating a role-specific object and setting it up (e.g. by sending - the title, app ID, size constraints, parent, etc), the client must - perform an initial commit without any buffer attached. The compositor - will reply with initial wl_surface state such as - wl_surface.preferred_buffer_scale followed by an xdg_surface.configure - event. The client must acknowledge it and is then allowed to attach a - buffer to map the surface. - - Mapping an xdg_surface-based role surface is defined as making it - possible for the surface to be shown by the compositor. Note that - a mapped surface is not guaranteed to be visible once it is mapped. - - For an xdg_surface to be mapped by the compositor, the following - conditions must be met: - (1) the client has assigned an xdg_surface-based role to the surface - (2) the client has set and committed the xdg_surface state and the - role-dependent state to the surface - (3) the client has committed a buffer to the surface - - A newly-unmapped surface is considered to have met condition (1) out - of the 3 required conditions for mapping a surface if its role surface - has not been destroyed, i.e. the client must perform the initial commit - again before attaching a buffer. - - - - - - - - - - - - - - Destroy the xdg_surface object. An xdg_surface must only be destroyed - after its role object has been destroyed, otherwise - a defunct_role_object error is raised. - - - - - - This creates an xdg_toplevel object for the given xdg_surface and gives - the associated wl_surface the xdg_toplevel role. - - See the documentation of xdg_toplevel for more details about what an - xdg_toplevel is and how it is used. - - - - - - - This creates an xdg_popup object for the given xdg_surface and gives - the associated wl_surface the xdg_popup role. - - If null is passed as a parent, a parent surface must be specified using - some other protocol, before committing the initial state. - - See the documentation of xdg_popup for more details about what an - xdg_popup is and how it is used. - - - - - - - - - The window geometry of a surface is its "visible bounds" from the - user's perspective. Client-side decorations often have invisible - portions like drop-shadows which should be ignored for the - purposes of aligning, placing and constraining windows. - - The window geometry is double-buffered state, see wl_surface.commit. - - When maintaining a position, the compositor should treat the (x, y) - coordinate of the window geometry as the top left corner of the window. - A client changing the (x, y) window geometry coordinate should in - general not alter the position of the window. - - Once the window geometry of the surface is set, it is not possible to - unset it, and it will remain the same until set_window_geometry is - called again, even if a new subsurface or buffer is attached. - - If never set, the value is the full bounds of the surface, - including any subsurfaces. This updates dynamically on every - commit. This unset is meant for extremely simple clients. - - The arguments are given in the surface-local coordinate space of - the wl_surface associated with this xdg_surface, and may extend outside - of the wl_surface itself to mark parts of the subsurface tree as part of - the window geometry. - - When applied, the effective window geometry will be the set window - geometry clamped to the bounding rectangle of the combined - geometry of the surface of the xdg_surface and the associated - subsurfaces. - - The effective geometry will not be recalculated unless a new call to - set_window_geometry is done and the new pending surface state is - subsequently applied. - - The width and height of the effective window geometry must be - greater than zero. Setting an invalid size will raise an - invalid_size error. - - - - - - - - - - When a configure event is received, if a client commits the - surface in response to the configure event, then the client - must make an ack_configure request sometime before the commit - request, passing along the serial of the configure event. - - For instance, for toplevel surfaces the compositor might use this - information to move a surface to the top left only when the client has - drawn itself for the maximized or fullscreen state. - - If the client receives multiple configure events before it - can respond to one, it only has to ack the last configure event. - Acking a configure event that was never sent raises an invalid_serial - error. - - A client is not required to commit immediately after sending - an ack_configure request - it may even ack_configure several times - before its next surface commit. - - A client may send multiple ack_configure requests before committing, but - only the last request sent before a commit indicates which configure - event the client really is responding to. - - Sending an ack_configure request consumes the serial number sent with - the request, as well as serial numbers sent by all configure events - sent on this xdg_surface prior to the configure event referenced by - the committed serial. - - It is an error to issue multiple ack_configure requests referencing a - serial from the same configure event, or to issue an ack_configure - request referencing a serial from a configure event issued before the - event identified by the last ack_configure request for the same - xdg_surface. Doing so will raise an invalid_serial error. - - - - - - - The configure event marks the end of a configure sequence. A configure - sequence is a set of one or more events configuring the state of the - xdg_surface, including the final xdg_surface.configure event. - - Where applicable, xdg_surface surface roles will during a configure - sequence extend this event as a latched state sent as events before the - xdg_surface.configure event. Such events should be considered to make up - a set of atomically applied configuration states, where the - xdg_surface.configure commits the accumulated state. - - Clients should arrange their surface for the new states, and then send - an ack_configure request with the serial sent in this configure event at - some point before committing the new surface. - - If the client receives multiple configure events before it can respond - to one, it is free to discard all but the last event it received. - - - - - - - - - This interface defines an xdg_surface role which allows a surface to, - among other things, set window-like properties such as maximize, - fullscreen, and minimize, set application-specific metadata like title and - id, and well as trigger user interactive operations such as interactive - resize and move. - - A xdg_toplevel by default is responsible for providing the full intended - visual representation of the toplevel, which depending on the window - state, may mean things like a title bar, window controls and drop shadow. - - Unmapping an xdg_toplevel means that the surface cannot be shown - by the compositor until it is explicitly mapped again. - All active operations (e.g., move, resize) are canceled and all - attributes (e.g. title, state, stacking, ...) are discarded for - an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to - the state it had right after xdg_surface.get_toplevel. The client - can re-map the toplevel by performing a commit without any buffer - attached, waiting for a configure event and handling it as usual (see - xdg_surface description). - - Attaching a null buffer to a toplevel unmaps the surface. - - - - - This request destroys the role surface and unmaps the surface; - see "Unmapping" behavior in interface section for details. - - - - - - - - - - - - Set the "parent" of this surface. This surface should be stacked - above the parent surface and all other ancestor surfaces. - - Parent surfaces should be set on dialogs, toolboxes, or other - "auxiliary" surfaces, so that the parent is raised when the dialog - is raised. - - Setting a null parent for a child surface unsets its parent. Setting - a null parent for a surface which currently has no parent is a no-op. - - Only mapped surfaces can have child surfaces. Setting a parent which - is not mapped is equivalent to setting a null parent. If a surface - becomes unmapped, its children's parent is set to the parent of - the now-unmapped surface. If the now-unmapped surface has no parent, - its children's parent is unset. If the now-unmapped surface becomes - mapped again, its parent-child relationship is not restored. - - The parent toplevel must not be one of the child toplevel's - descendants, and the parent must be different from the child toplevel, - otherwise the invalid_parent protocol error is raised. - - - - - - - Set a short title for the surface. - - This string may be used to identify the surface in a task bar, - window list, or other user interface elements provided by the - compositor. - - The string must be encoded in UTF-8. - - - - - - - Set an application identifier for the surface. - - The app ID identifies the general class of applications to which - the surface belongs. The compositor can use this to group multiple - surfaces together, or to determine how to launch a new application. - - For D-Bus activatable applications, the app ID is used as the D-Bus - service name. - - The compositor shell will try to group application surfaces together - by their app ID. As a best practice, it is suggested to select app - ID's that match the basename of the application's .desktop file. - For example, "org.freedesktop.FooViewer" where the .desktop file is - "org.freedesktop.FooViewer.desktop". - - Like other properties, a set_app_id request can be sent after the - xdg_toplevel has been mapped to update the property. - - See the desktop-entry specification [0] for more details on - application identifiers and how they relate to well-known D-Bus - names and .desktop files. - - [0] https://standards.freedesktop.org/desktop-entry-spec/ - - - - - - - Clients implementing client-side decorations might want to show - a context menu when right-clicking on the decorations, giving the - user a menu that they can use to maximize or minimize the window. - - This request asks the compositor to pop up such a window menu at - the given position, relative to the local surface coordinates of - the parent surface. There are no guarantees as to what menu items - the window menu contains, or even if a window menu will be drawn - at all. - - This request must be used in response to some sort of user action - like a button press, key press, or touch down event. - - - - - - - - - - Start an interactive, user-driven move of the surface. - - This request must be used in response to some sort of user action - like a button press, key press, or touch down event. The passed - serial is used to determine the type of interactive move (touch, - pointer, etc). - - The server may ignore move requests depending on the state of - the surface (e.g. fullscreen or maximized), or if the passed serial - is no longer valid. - - If triggered, the surface will lose the focus of the device - (wl_pointer, wl_touch, etc) used for the move. It is up to the - compositor to visually indicate that the move is taking place, such as - updating a pointer cursor, during the move. There is no guarantee - that the device focus will return when the move is completed. - - - - - - - - These values are used to indicate which edge of a surface - is being dragged in a resize operation. - - - - - - - - - - - - - - - Start a user-driven, interactive resize of the surface. - - This request must be used in response to some sort of user action - like a button press, key press, or touch down event. The passed - serial is used to determine the type of interactive resize (touch, - pointer, etc). - - The server may ignore resize requests depending on the state of - the surface (e.g. fullscreen or maximized). - - If triggered, the client will receive configure events with the - "resize" state enum value and the expected sizes. See the "resize" - enum value for more details about what is required. The client - must also acknowledge configure events using "ack_configure". After - the resize is completed, the client will receive another "configure" - event without the resize state. - - If triggered, the surface also will lose the focus of the device - (wl_pointer, wl_touch, etc) used for the resize. It is up to the - compositor to visually indicate that the resize is taking place, - such as updating a pointer cursor, during the resize. There is no - guarantee that the device focus will return when the resize is - completed. - - The edges parameter specifies how the surface should be resized, and - is one of the values of the resize_edge enum. Values not matching - a variant of the enum will cause the invalid_resize_edge protocol error. - The compositor may use this information to update the surface position - for example when dragging the top left corner. The compositor may also - use this information to adapt its behavior, e.g. choose an appropriate - cursor image. - - - - - - - - - The different state values used on the surface. This is designed for - state values like maximized, fullscreen. It is paired with the - configure event to ensure that both the client and the compositor - setting the state can be synchronized. - - States set in this way are double-buffered, see wl_surface.commit. - - - - The surface is maximized. The window geometry specified in the configure - event must be obeyed by the client, or the xdg_wm_base.invalid_surface_state - error is raised. - - The client should draw without shadow or other - decoration outside of the window geometry. - - - - - The surface is fullscreen. The window geometry specified in the - configure event is a maximum; the client cannot resize beyond it. For - a surface to cover the whole fullscreened area, the geometry - dimensions must be obeyed by the client. For more details, see - xdg_toplevel.set_fullscreen. - - - - - The surface is being resized. The window geometry specified in the - configure event is a maximum; the client cannot resize beyond it. - Clients that have aspect ratio or cell sizing configuration can use - a smaller size, however. - - - - - Client window decorations should be painted as if the window is - active. Do not assume this means that the window actually has - keyboard or pointer focus. - - - - - The window is currently in a tiled layout and the left edge is - considered to be adjacent to another part of the tiling grid. - - The client should draw without shadow or other decoration outside of - the window geometry on the left edge. - - - - - The window is currently in a tiled layout and the right edge is - considered to be adjacent to another part of the tiling grid. - - The client should draw without shadow or other decoration outside of - the window geometry on the right edge. - - - - - The window is currently in a tiled layout and the top edge is - considered to be adjacent to another part of the tiling grid. - - The client should draw without shadow or other decoration outside of - the window geometry on the top edge. - - - - - The window is currently in a tiled layout and the bottom edge is - considered to be adjacent to another part of the tiling grid. - - The client should draw without shadow or other decoration outside of - the window geometry on the bottom edge. - - - - - The surface is currently not ordinarily being repainted; for - example because its content is occluded by another window, or its - outputs are switched off due to screen locking. - - - - - The left edge of the window is currently constrained, meaning it - shouldn't attempt to resize from that edge. It can for example mean - it's tiled next to a monitor edge on the constrained side of the - window. - - - - - The right edge of the window is currently constrained, meaning it - shouldn't attempt to resize from that edge. It can for example mean - it's tiled next to a monitor edge on the constrained side of the - window. - - - - - The top edge of the window is currently constrained, meaning it - shouldn't attempt to resize from that edge. It can for example mean - it's tiled next to a monitor edge on the constrained side of the - window. - - - - - The bottom edge of the window is currently constrained, meaning it - shouldn't attempt to resize from that edge. It can for example mean - it's tiled next to a monitor edge on the constrained side of the - window. - - - - - - - Set a maximum size for the window. - - The client can specify a maximum size so that the compositor does - not try to configure the window beyond this size. - - The width and height arguments are in window geometry coordinates. - See xdg_surface.set_window_geometry. - - Values set in this way are double-buffered, see wl_surface.commit. - - The compositor can use this information to allow or disallow - different states like maximize or fullscreen and draw accurate - animations. - - Similarly, a tiling window manager may use this information to - place and resize client windows in a more effective way. - - The client should not rely on the compositor to obey the maximum - size. The compositor may decide to ignore the values set by the - client and request a larger size. - - If never set, or a value of zero in the request, means that the - client has no expected maximum size in the given dimension. - As a result, a client wishing to reset the maximum size - to an unspecified state can use zero for width and height in the - request. - - Requesting a maximum size to be smaller than the minimum size of - a surface is illegal and will result in an invalid_size error. - - The width and height must be greater than or equal to zero. Using - strictly negative values for width or height will result in a - invalid_size error. - - - - - - - - Set a minimum size for the window. - - The client can specify a minimum size so that the compositor does - not try to configure the window below this size. - - The width and height arguments are in window geometry coordinates. - See xdg_surface.set_window_geometry. - - Values set in this way are double-buffered, see wl_surface.commit. - - The compositor can use this information to allow or disallow - different states like maximize or fullscreen and draw accurate - animations. - - Similarly, a tiling window manager may use this information to - place and resize client windows in a more effective way. - - The client should not rely on the compositor to obey the minimum - size. The compositor may decide to ignore the values set by the - client and request a smaller size. - - If never set, or a value of zero in the request, means that the - client has no expected minimum size in the given dimension. - As a result, a client wishing to reset the minimum size - to an unspecified state can use zero for width and height in the - request. - - Requesting a minimum size to be larger than the maximum size of - a surface is illegal and will result in an invalid_size error. - - The width and height must be greater than or equal to zero. Using - strictly negative values for width and height will result in a - invalid_size error. - - - - - - - - Maximize the surface. - - After requesting that the surface should be maximized, the compositor - will respond by emitting a configure event. Whether this configure - actually sets the window maximized is subject to compositor policies. - The client must then update its content, drawing in the configured - state. The client must also acknowledge the configure when committing - the new content (see ack_configure). - - It is up to the compositor to decide how and where to maximize the - surface, for example which output and what region of the screen should - be used. - - If the surface was already maximized, the compositor will still emit - a configure event with the "maximized" state. - - If the surface is in a fullscreen state, this request has no direct - effect. It may alter the state the surface is returned to when - unmaximized unless overridden by the compositor. - - - - - - Unmaximize the surface. - - After requesting that the surface should be unmaximized, the compositor - will respond by emitting a configure event. Whether this actually - un-maximizes the window is subject to compositor policies. - If available and applicable, the compositor will include the window - geometry dimensions the window had prior to being maximized in the - configure event. The client must then update its content, drawing it in - the configured state. The client must also acknowledge the configure - when committing the new content (see ack_configure). - - It is up to the compositor to position the surface after it was - unmaximized; usually the position the surface had before maximizing, if - applicable. - - If the surface was already not maximized, the compositor will still - emit a configure event without the "maximized" state. - - If the surface is in a fullscreen state, this request has no direct - effect. It may alter the state the surface is returned to when - unmaximized unless overridden by the compositor. - - - - - - Make the surface fullscreen. - - After requesting that the surface should be fullscreened, the - compositor will respond by emitting a configure event. Whether the - client is actually put into a fullscreen state is subject to compositor - policies. The client must also acknowledge the configure when - committing the new content (see ack_configure). - - The output passed by the request indicates the client's preference as - to which display it should be set fullscreen on. If this value is NULL, - it's up to the compositor to choose which display will be used to map - this surface. - - If the surface doesn't cover the whole output, the compositor will - position the surface in the center of the output and compensate with - with border fill covering the rest of the output. The content of the - border fill is undefined, but should be assumed to be in some way that - attempts to blend into the surrounding area (e.g. solid black). - - If the fullscreened surface is not opaque, the compositor must make - sure that other screen content not part of the same surface tree (made - up of subsurfaces, popups or similarly coupled surfaces) are not - visible below the fullscreened surface. - - - - - - - Make the surface no longer fullscreen. - - After requesting that the surface should be unfullscreened, the - compositor will respond by emitting a configure event. - Whether this actually removes the fullscreen state of the client is - subject to compositor policies. - - Making a surface unfullscreen sets states for the surface based on the following: - * the state(s) it may have had before becoming fullscreen - * any state(s) decided by the compositor - * any state(s) requested by the client while the surface was fullscreen - - The compositor may include the previous window geometry dimensions in - the configure event, if applicable. - - The client must also acknowledge the configure when committing the new - content (see ack_configure). - - - - - - Request that the compositor minimize your surface. There is no - way to know if the surface is currently minimized, nor is there - any way to unset minimization on this surface. - - If you are looking to throttle redrawing when minimized, please - instead use the wl_surface.frame event for this, as this will - also work with live previews on windows in Alt-Tab, Expose or - similar compositor features. - - - - - - This configure event asks the client to resize its toplevel surface or - to change its state. The configured state should not be applied - immediately. See xdg_surface.configure for details. - - The width and height arguments specify a hint to the window - about how its surface should be resized in window geometry - coordinates. See set_window_geometry. - - If the width or height arguments are zero, it means the client - should decide its own window dimension. This may happen when the - compositor needs to configure the state of the surface but doesn't - have any information about any previous or expected dimension. - - The states listed in the event specify how the width/height - arguments should be interpreted, and possibly how it should be - drawn. - - Clients must send an ack_configure in response to this event. See - xdg_surface.configure and xdg_surface.ack_configure for details. - - - - - - - - - The close event is sent by the compositor when the user - wants the surface to be closed. This should be equivalent to - the user clicking the close button in client-side decorations, - if your application has any. - - This is only a request that the user intends to close the - window. The client may choose to ignore this request, or show - a dialog to ask the user to save their data, etc. - - - - - - - - The configure_bounds event may be sent prior to a xdg_toplevel.configure - event to communicate the bounds a window geometry size is recommended - to constrain to. - - The passed width and height are in surface coordinate space. If width - and height are 0, it means bounds is unknown and equivalent to as if no - configure_bounds event was ever sent for this surface. - - The bounds can for example correspond to the size of a monitor excluding - any panels or other shell components, so that a surface isn't created in - a way that it cannot fit. - - The bounds may change at any point, and in such a case, a new - xdg_toplevel.configure_bounds will be sent, followed by - xdg_toplevel.configure and xdg_surface.configure. - - - - - - - - - - - - - - - - - This event advertises the capabilities supported by the compositor. If - a capability isn't supported, clients should hide or disable the UI - elements that expose this functionality. For instance, if the - compositor doesn't advertise support for minimized toplevels, a button - triggering the set_minimized request should not be displayed. - - The compositor will ignore requests it doesn't support. For instance, - a compositor which doesn't advertise support for minimized will ignore - set_minimized requests. - - Compositors must send this event once before the first - xdg_surface.configure event. When the capabilities change, compositors - must send this event again and then send an xdg_surface.configure - event. - - The configured state should not be applied immediately. See - xdg_surface.configure for details. - - The capabilities are sent as an array of 32-bit unsigned integers in - native endianness. - - - - - - - - A popup surface is a short-lived, temporary surface. It can be used to - implement for example menus, popovers, tooltips and other similar user - interface concepts. - - A popup can be made to take an explicit grab. See xdg_popup.grab for - details. - - When the popup is dismissed, a popup_done event will be sent out, and at - the same time the surface will be unmapped. See the xdg_popup.popup_done - event for details. - - Explicitly destroying the xdg_popup object will also dismiss the popup and - unmap the surface. Clients that want to dismiss the popup when another - surface of their own is clicked should dismiss the popup using the destroy - request. - - A newly created xdg_popup will be stacked on top of all previously created - xdg_popup surfaces associated with the same xdg_toplevel. - - The parent of an xdg_popup must be mapped (see the xdg_surface - description) before the xdg_popup itself. - - The client must call wl_surface.commit on the corresponding wl_surface - for the xdg_popup state to take effect. - - - - - - - - - This destroys the popup. Explicitly destroying the xdg_popup - object will also dismiss the popup, and unmap the surface. - - If this xdg_popup is not the "topmost" popup, the - xdg_wm_base.not_the_topmost_popup protocol error will be sent. - - - - - - This request makes the created popup take an explicit grab. An explicit - grab will be dismissed when the user dismisses the popup, or when the - client destroys the xdg_popup. This can be done by the user clicking - outside the surface, using the keyboard, or even locking the screen - through closing the lid or a timeout. - - If the compositor denies the grab, the popup will be immediately - dismissed. - - This request must be used in response to some sort of user action like a - button press, key press, or touch down event. The serial number of the - event should be passed as 'serial'. - - The parent of a grabbing popup must either be an xdg_toplevel surface or - another xdg_popup with an explicit grab. If the parent is another - xdg_popup it means that the popups are nested, with this popup now being - the topmost popup. - - Nested popups must be destroyed in the reverse order they were created - in, e.g. the only popup you are allowed to destroy at all times is the - topmost one. - - When compositors choose to dismiss a popup, they may dismiss every - nested grabbing popup as well. When a compositor dismisses popups, it - will follow the same dismissing order as required from the client. - - If the topmost grabbing popup is destroyed, the grab will be returned to - the parent of the popup, if that parent previously had an explicit grab. - - If the parent is a grabbing popup which has already been dismissed, this - popup will be immediately dismissed. If the parent is a popup that did - not take an explicit grab, an error will be raised. - - During a popup grab, the client owning the grab will receive pointer - and touch events for all their surfaces as normal (similar to an - "owner-events" grab in X11 parlance), while the top most grabbing popup - will always have keyboard focus. - - - - - - - - This event asks the popup surface to configure itself given the - configuration. The configured state should not be applied immediately. - See xdg_surface.configure for details. - - The x and y arguments represent the position the popup was placed at - given the xdg_positioner rule, relative to the upper left corner of the - window geometry of the parent surface. - - For version 2 or older, the configure event for an xdg_popup is only - ever sent once for the initial configuration. Starting with version 3, - it may be sent again if the popup is setup with an xdg_positioner with - set_reactive requested, or in response to xdg_popup.reposition requests. - - - - - - - - - - The popup_done event is sent out when a popup is dismissed by the - compositor. The client should destroy the xdg_popup object at this - point. - - - - - - - - Reposition an already-mapped popup. The popup will be placed given the - details in the passed xdg_positioner object, and a - xdg_popup.repositioned followed by xdg_popup.configure and - xdg_surface.configure will be emitted in response. Any parameters set - by the previous positioner will be discarded. - - The passed token will be sent in the corresponding - xdg_popup.repositioned event. The new popup position will not take - effect until the corresponding configure event is acknowledged by the - client. See xdg_popup.repositioned for details. The token itself is - opaque, and has no other special meaning. - - If multiple reposition requests are sent, the compositor may skip all - but the last one. - - If the popup is repositioned in response to a configure event for its - parent, the client should send an xdg_positioner.set_parent_configure - and possibly an xdg_positioner.set_parent_size request to allow the - compositor to properly constrain the popup. - - If the popup is repositioned together with a parent that is being - resized, but not in response to a configure event, the client should - send an xdg_positioner.set_parent_size request. - - - - - - - - The repositioned event is sent as part of a popup configuration - sequence, together with xdg_popup.configure and lastly - xdg_surface.configure to notify the completion of a reposition request. - - The repositioned event is to notify about the completion of a - xdg_popup.reposition request. The token argument is the token passed - in the xdg_popup.reposition request. - - Immediately after this event is emitted, xdg_popup.configure and - xdg_surface.configure will be sent with the updated size and position, - as well as a new configure serial. - - The client should optionally update the content of the popup, but must - acknowledge the new popup configuration for the new position to take - effect. See xdg_surface.ack_configure for details. - - - - - - From d792dc3fb95c63f6c607481623de3635ada27fc8 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 17:18:32 +0200 Subject: [PATCH 10/25] utils: Extract double_time, easing to libs --- android/xscreensaver/jni/Android.mk | 2 + driver/Makefile.in | 13 +- driver/dialog.c | 18 +- driver/fade.c | 16 +- hacks/Makefile.in | 25 ++- hacks/droste.c | 18 +- hacks/filmleader.c | 18 +- hacks/glx/Makefile.in | 106 +++++++---- hacks/glx/carousel.c | 9 +- hacks/glx/chompytower.c | 46 +---- hacks/glx/crumbler.c | 30 +-- hacks/glx/cubestack.c | 24 +-- hacks/glx/cubetwist.c | 24 +-- hacks/glx/dumpsterfire.c | 29 +-- hacks/glx/dymaxionmap.c | 48 +---- hacks/glx/esper.c | 19 +- hacks/glx/gibson.c | 25 +-- hacks/glx/glhanoi.c | 20 +- hacks/glx/glslideshow.c | 19 +- hacks/glx/grab-ximage.c | 20 +- hacks/glx/handsy.c | 20 +- hacks/glx/hydrostat.c | 27 +-- hacks/glx/mapscroller.c | 22 +-- hacks/glx/mirrorblob.c | 21 +-- hacks/glx/nakagin.c | 42 +---- hacks/glx/raverhoop.c | 24 +-- hacks/glx/skulloop.c | 24 +-- hacks/glx/sonar-icmp.c | 18 +- hacks/glx/sonar.c | 20 +- hacks/glx/squirtorus.c | 24 +-- hacks/glx/tronbit.c | 20 +- hacks/glx/unknownpleasures.c | 44 +---- hacks/glx/voronoi.c | 21 +-- hacks/m6502.c | 19 +- hacks/pong.c | 16 +- hacks/recanim.c | 18 +- hacks/tessellimage.c | 20 +- hacks/vfeedback.c | 53 ++---- jwxyz/jwxyz-android.c | 21 +-- jwxyz/jwxyz-timers.c | 18 +- utils/Makefile.in | 14 +- utils/doubletime.c | 28 +++ utils/doubletime.h | 18 ++ utils/easing.c | 282 ++++++++++++++++++++++++++++ utils/easing.h | 32 ++++ utils/erase.c | 18 +- utils/screenshot.c | 16 +- 47 files changed, 598 insertions(+), 831 deletions(-) create mode 100644 utils/doubletime.c create mode 100644 utils/doubletime.h create mode 100644 utils/easing.c create mode 100644 utils/easing.h diff --git a/android/xscreensaver/jni/Android.mk b/android/xscreensaver/jni/Android.mk index 28e0e1a16..92f906629 100644 --- a/android/xscreensaver/jni/Android.mk +++ b/android/xscreensaver/jni/Android.mk @@ -174,6 +174,8 @@ LOCAL_SRC_FILES += \ utils/aligned_malloc.c \ utils/colorbars.c \ utils/colors.c \ + utils/doubletime.c \ + utils/easing.c \ utils/erase.c \ utils/font-retry.c \ utils/grabclient.c \ diff --git a/driver/Makefile.in b/driver/Makefile.in index db7dd8768..dc7e56661 100644 --- a/driver/Makefile.in +++ b/driver/Makefile.in @@ -179,6 +179,7 @@ GFX_OBJS = xscreensaver-gfx.o screens.o windows.o subprocs.o \ $(UTILS_BIN)/utf8wc.o \ $(UTILS_BIN)/xshm.o \ $(UTILS_BIN)/aligned_malloc.o \ + $(UTILS_BIN)/doubletime.o \ $(GFX_GL_OBJS) GFX_GL_OBJS = @GFX_GL_OBJS@ GFX_GL_OBJS_1 = $(UTILS_BIN)/visual-gl.o $(UTILS_BIN)/pow2.o @@ -210,6 +211,7 @@ AUTH_OBJS_1 = dialog.o passwd.o setuid.o \ $(UTILS_BIN)/font-retry.o \ $(UTILS_BIN)/yarandom.o \ $(UTILS_BIN)/usleep.o \ + $(UTILS_BIN)/doubletime.o \ $(UTILS_BIN)/resources.o \ $(UTILS_BIN)/logo.o \ $(UTILS_BIN)/minixpm.o @@ -240,7 +242,8 @@ GTK_OBJS = demo-Gtk.o demo-Gtk-conf.o demo-Gtk-resources.o \ $(UTILS_BIN)/resources.o \ $(UTILS_BIN)/visual.o \ $(UTILS_BIN)/screenshot.o \ - $(UTILS_BIN)/usleep.o + $(UTILS_BIN)/usleep.o \ + $(UTILS_BIN)/doubletime.o GTK_LIBS = $(LIBS_PRE) $(INTL_LIBS) $(XDPMS_LIBS) \ $(XINERAMA_LIBS) $(XML_LIBS) @GTK_LIBS@ \ -lXt -lX11 -lXext -lXi $(LIBS_POST) @@ -845,6 +848,7 @@ $(UTILS_BIN)/aligned_malloc.o: $(UTILS_SRC)/aligned_malloc.c $(UTILS_BIN)/screenshot.o: $(UTILS_SRC)/screenshot.c $(UTILS_BIN)/visual-gl.o: $(UTILS_SRC)/visual-gl.c $(UTILS_BIN)/pow2.o: $(UTILS_SRC)/pow2.c +$(UTILS_BIN)/doubletime.o: $(UTILS_SRC)/doubletime.c UTIL_OBJS = $(UTILS_BIN)/overlay.o \ @@ -867,7 +871,8 @@ UTIL_OBJS = $(UTILS_BIN)/overlay.o \ $(UTILS_BIN)/aligned_malloc.o \ $(UTILS_BIN)/screenshot.o \ $(UTILS_BIN)/visual-gl.o \ - $(UTILS_BIN)/pow2.o + $(UTILS_BIN)/pow2.o \ + $(UTILS_BIN)/doubletime.o $(UTIL_OBJS): $(MAKE2CC) -C $(UTILS_BIN) $(@F) @@ -1173,7 +1178,7 @@ TEST_FADE_OBJS = test-fade.o fade.o blurb.o atoms.o clientmsg.o xinput.o \ $(UTILS_BIN)/visual.o $(UTILS_BIN)/resources.o $(UTILS_BIN)/usleep.o \ $(UTILS_BIN)/logo.o $(UTILS_BIN)/minixpm.o $(UTILS_BIN)/xshm.o \ $(UTILS_BIN)/xmu.o $(UTILS_BIN)/aligned_malloc.o \ - $(UTILS_BIN)/screenshot.o $(GFX_GL_OBJS) + $(UTILS_BIN)/screenshot.o $(UTILS_BIN)/doubletime.o $(GFX_GL_OBJS) test-fade: $(TEST_FADE_OBJS) $(CC) $(LDFLAGS) -o $@ $(TEST_FADE_OBJS) $(GFX_LIBS) @@ -1240,6 +1245,7 @@ dialog.o: $(srcdir)/blurb.h dialog.o: ../config.h dialog.o: $(srcdir)/prefs.h dialog.o: $(srcdir)/screens.h +dialog.o: $(UTILS_SRC)/doubletime.h dialog.o: $(UTILS_SRC)/font-retry.h dialog.o: $(UTILS_SRC)/resources.h dialog.o: $(UTILS_SRC)/usleep.h @@ -1264,6 +1270,7 @@ fade.o: $(srcdir)/blurb.h fade.o: $(srcdir)/clientmsg.h fade.o: ../config.h fade.o: $(srcdir)/fade.h +fade.o: $(UTILS_SRC)/doubletime.h fade.o: $(UTILS_SRC)/pow2.h fade.o: $(UTILS_SRC)/screenshot.h fade.o: $(UTILS_SRC)/usleep.h diff --git a/driver/dialog.c b/driver/dialog.c index 7b4336741..dff0d9a7e 100644 --- a/driver/dialog.c +++ b/driver/dialog.c @@ -84,6 +84,7 @@ #include "prefs.h" #include "usleep.h" #include "utf8wc.h" +#include "doubletime.h" #undef countof #define countof(x) (sizeof((x))/sizeof((*x))) @@ -980,21 +981,6 @@ get_keyboard_layout (window_state *ws) } -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static void create_window (window_state *ws, int w, int h) { @@ -1473,7 +1459,7 @@ window_draw (window_state *ws) Thank you! - jwz, 2014, 2016, 2018, 2021. + jwz, 2014, 2016, 2018, 2021, 2025. PS: In particular, since Debian refuses to upgrade software on any kind of rational timeline, I have asked that they stop shipping diff --git a/driver/fade.c b/driver/fade.c index c28989401..3674c1f41 100644 --- a/driver/fade.c +++ b/driver/fade.c @@ -113,6 +113,7 @@ #include "clientmsg.h" #include "xmu.h" #include "pow2.h" +#include "doubletime.h" #include "screenshot.h" /* Since gamma fading doesn't work on the Raspberry Pi, probably the single @@ -165,21 +166,6 @@ static int xshm_fade (XtAppContext, Display *, Bool out_p, Bool from_desktop_p, fade_state *); -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - #ifdef HAVE_XINPUT static int xi_opcode = -1; #endif diff --git a/hacks/Makefile.in b/hacks/Makefile.in index 89a9861de..b0825b1c3 100644 --- a/hacks/Makefile.in +++ b/hacks/Makefile.in @@ -82,7 +82,8 @@ UTIL_SRCS = $(UTILS_SRC)/alpha.c $(UTILS_SRC)/colors.c \ $(UTILS_SRC)/xshm.c $(UTILS_SRC)/xdbe.c \ $(UTILS_SRC)/textclient.c $(UTILS_SRC)/aligned_malloc.c \ $(UTILS_SRC)/thread_util.c $(UTILS_SRC)/pow2.c \ - $(UTILS_SRC)/font-retry.c + $(UTILS_SRC)/font-retry.c $(UTILS_SRC)/easing.c \ + $(UTILS_SRC)/doubletime.c UTIL_OBJS = $(UTILS_BIN)/alpha.o $(UTILS_BIN)/colors.o \ $(UTILS_BIN)/grabclient.o \ $(UTILS_BIN)/hsv.o $(UTILS_BIN)/resources.o \ @@ -94,7 +95,8 @@ UTIL_OBJS = $(UTILS_BIN)/alpha.o $(UTILS_BIN)/colors.o \ $(UTILS_BIN)/textclient.o $(UTILS_BIN)/aligned_malloc.o \ $(UTILS_BIN)/thread_util.o $(UTILS_BIN)/pow2.o \ $(UTILS_BIN)/xft.o $(UTILS_BIN)/xftwrap.o \ - $(UTILS_BIN)/utf8wc.o $(UTILS_BIN)/font-retry.o + $(UTILS_BIN)/utf8wc.o $(UTILS_BIN)/font-retry.o \ + $(UTILS_BIN)/easing.o $(UTILS_BIN)/doubletime.o SRCS = xscreensaver-getimage.c \ attraction.c blitspin.c bouboule.c braid.c bubbles.c \ @@ -202,7 +204,7 @@ RETIRED_EXES = ant bubbles critical flag forest hyperball hypercube laser \ HACK_OBJS_1 = fps.o $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \ $(UTILS_BIN)/usleep.o $(UTILS_BIN)/yarandom.o \ $(UTILS_BIN)/utf8wc.o $(UTILS_BIN)/font-retry.o \ - $(UTILS_BIN)/xmu.o @XFT_OBJS@ @ANIM_OBJS@ + $(UTILS_BIN)/xmu.o $(DT) @XFT_OBJS@ @ANIM_OBJS@ HACK_OBJS = screenhack.o $(HACK_OBJS_1) XLOCK_OBJS = screenhack.o xlockmore.o $(COLOR_OBJS) $(HACK_OBJS_1) \ $(ERASE) @@ -491,6 +493,7 @@ $(UTILS_BIN)/aligned_malloc.o: $(UTILS_SRC)/aligned_malloc.c $(UTILS_BIN)/thread_util.o: $(UTILS_SRC)/thread_util.c $(UTILS_BIN)/pow2.o: $(UTILS_SRC)/pow2.c $(UTILS_BIN)/font-retry.o: $(UTILS_SRC)/font-retry.c +$(UTILS_BIN)/easing.o: $(UTILS_SRC)/easing.c @@ -519,6 +522,7 @@ ALP = $(UTILS_BIN)/alpha.o HSV = $(UTILS_BIN)/hsv.o SPL = $(UTILS_BIN)/spline.o GRAB = $(GRAB_OBJS) +DT = $(UTILS_BIN)/doubletime.o ERASE = $(UTILS_BIN)/erase.o COL = $(COLOR_OBJS) SHM = $(XSHM_OBJS) @@ -551,7 +555,7 @@ GETIMG_OBJS = xscreensaver-getimage.o \ $(UTILS_BIN)/colors.o \ $(UTILS_BIN)/logo.o $(UTILS_BIN)/minixpm.o \ $(UTILS_BIN)/screenshot.o $(UTILS_BIN)/xmu.o \ - $(DRIVER_BIN)/prefs.o + $(DRIVER_BIN)/prefs.o $(DT) GETIMG_LIBS = $(LIBS) $(X_LIBS) $(PNG_LIBS) $(JPEG_LIBS) \ $(X_PRE_LIBS) -lXt -lX11 -lXext $(X_EXTRA_LIBS) @@ -885,8 +889,9 @@ glitchpeg: glitchpeg.o $(HACK_OBJS) $(PNG) filmleader: filmleader.o $(HACK_OBJS) $(ATV) $(GRAB) $(PNG) $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(ATV) $(GRAB) $(PNG) $(PNG_LIBS) $(HACK_LIBS) $(THRL) -vfeedback: vfeedback.o $(HACK_OBJS) $(ATV) $(GRAB) $(PNG) - $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(ATV) $(GRAB) $(PNG) $(PNG_LIBS) $(HACK_LIBS) $(THRL) +EASE = $(UTILS_BIN)/easing.o +vfeedback: vfeedback.o $(HACK_OBJS) $(ATV) $(GRAB) $(PNG) $(EASE) + $(CC_HACK) -o $@ $@.o $(HACK_OBJS) $(ATV) $(GRAB) $(PNG) $(EASE) $(PNG_LIBS) $(HACK_LIBS) $(THRL) MARBLING_OBJS=$(COLOR_OBJS) $(THRO) $(XSHM_OBJS) $(HACK_OBJS) marbling: marbling.o $(MARBLING_OBJS) @@ -1713,6 +1718,7 @@ droste.o: $(srcdir)/screenhackI.h droste.o: $(srcdir)/screenhack.h droste.o: $(UTILS_SRC)/aligned_malloc.h droste.o: $(UTILS_SRC)/colors.h +droste.o: $(UTILS_SRC)/doubletime.h droste.o: $(UTILS_SRC)/font-retry.h droste.o: $(UTILS_SRC)/grabclient.h droste.o: $(UTILS_SRC)/hsv.h @@ -1825,6 +1831,7 @@ filmleader.o: $(srcdir)/screenhackI.h filmleader.o: $(srcdir)/screenhack.h filmleader.o: $(UTILS_SRC)/aligned_malloc.h filmleader.o: $(UTILS_SRC)/colors.h +filmleader.o: $(UTILS_SRC)/doubletime.h filmleader.o: $(UTILS_SRC)/font-retry.h filmleader.o: $(UTILS_SRC)/grabclient.h filmleader.o: $(UTILS_SRC)/hsv.h @@ -2406,6 +2413,7 @@ m6502.o: $(srcdir)/screenhackI.h m6502.o: $(srcdir)/screenhack.h m6502.o: $(UTILS_SRC)/aligned_malloc.h m6502.o: $(UTILS_SRC)/colors.h +m6502.o: $(UTILS_SRC)/doubletime.h m6502.o: $(UTILS_SRC)/font-retry.h m6502.o: $(UTILS_SRC)/grabclient.h m6502.o: $(UTILS_SRC)/hsv.h @@ -2752,6 +2760,7 @@ pong.o: $(srcdir)/screenhackI.h pong.o: $(srcdir)/screenhack.h pong.o: $(UTILS_SRC)/aligned_malloc.h pong.o: $(UTILS_SRC)/colors.h +pong.o: $(UTILS_SRC)/doubletime.h pong.o: $(UTILS_SRC)/font-retry.h pong.o: $(UTILS_SRC)/grabclient.h pong.o: $(UTILS_SRC)/hsv.h @@ -2827,6 +2836,7 @@ recanim.o: $(srcdir)/fps.h recanim.o: $(srcdir)/recanim.h recanim.o: $(srcdir)/screenhackI.h recanim.o: $(UTILS_SRC)/colors.h +recanim.o: $(UTILS_SRC)/doubletime.h recanim.o: $(UTILS_SRC)/font-retry.h recanim.o: $(UTILS_SRC)/grabclient.h recanim.o: $(UTILS_SRC)/hsv.h @@ -3165,6 +3175,7 @@ tessellimage.o: $(srcdir)/recanim.h tessellimage.o: $(srcdir)/screenhackI.h tessellimage.o: $(srcdir)/screenhack.h tessellimage.o: $(UTILS_SRC)/colors.h +tessellimage.o: $(UTILS_SRC)/doubletime.h tessellimage.o: $(UTILS_SRC)/font-retry.h tessellimage.o: $(UTILS_SRC)/grabclient.h tessellimage.o: $(UTILS_SRC)/hsv.h @@ -3275,6 +3286,8 @@ vfeedback.o: $(srcdir)/screenhackI.h vfeedback.o: $(srcdir)/screenhack.h vfeedback.o: $(UTILS_SRC)/aligned_malloc.h vfeedback.o: $(UTILS_SRC)/colors.h +vfeedback.o: $(UTILS_SRC)/doubletime.h +vfeedback.o: $(UTILS_SRC)/easing.h vfeedback.o: $(UTILS_SRC)/font-retry.h vfeedback.o: $(UTILS_SRC)/grabclient.h vfeedback.o: $(UTILS_SRC)/hsv.h diff --git a/hacks/droste.c b/hacks/droste.c index 0a5631a74..08478fdc4 100644 --- a/hacks/droste.c +++ b/hacks/droste.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright © 2023 Jamie Zawinski +/* xscreensaver, Copyright © 2023-2025 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 @@ -13,6 +13,7 @@ #include "pow2.h" #include "thread_util.h" #include "xshm.h" +#include "doubletime.h" #define DO_LOG_TABLES /* Dave's hairier and faster version */ @@ -122,21 +123,6 @@ struct thread { }; -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - /* Called for each thread, once at startup. */ static int droste_thread_create (void *t_raw, diff --git a/hacks/filmleader.c b/hacks/filmleader.c index 454b91d0e..3250d3b1a 100644 --- a/hacks/filmleader.c +++ b/hacks/filmleader.c @@ -1,4 +1,4 @@ -/* filmleader, Copyright (c) 2018-2019 Jamie Zawinski +/* filmleader, Copyright © 2018-2025 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 @@ -13,6 +13,7 @@ #include "screenhack.h" #include "analogtv.h" +#include "doubletime.h" #include @@ -132,21 +133,6 @@ filmleader_init (Display *dpy, Window window) } -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static unsigned long filmleader_draw (Display *dpy, Window window, void *closure) { diff --git a/hacks/glx/Makefile.in b/hacks/glx/Makefile.in index 5e6dfa778..08e0f0711 100644 --- a/hacks/glx/Makefile.in +++ b/hacks/glx/Makefile.in @@ -88,7 +88,7 @@ UTILDIR_OBJS = $(UTILS_BIN)/colors.o $(UTILS_BIN)/grabclient.o \ $(UTILS_BIN)/textclient.o $(UTILS_BIN)/async_netdb.o \ $(UTILS_BIN)/aligned_malloc.o $(UTILS_BIN)/thread_util.o \ $(UTILS_BIN)/spline.o $(UTILS_BIN)/pow2.o \ - $(UTILS_BIN)/font-retry.o + $(UTILS_BIN)/font-retry.o $(UTILS_BIN)/easing.o JWXYZ_OBJS = $(JWXYZ_BIN)/jwzgles.o HACKDIR_OBJS = $(HACK_BIN)/screenhack.o $(HACK_BIN)/xlockmore.o \ $(HACK_BIN)/fps.o $(HACK_BIN)/ximage-loader.o \ @@ -242,8 +242,10 @@ JWZGLES_OBJS = @JWZGLES_OBJS@ HACK_EXES_1 = @GL_EXES@ @GLE_EXES@ HACK_EXES = $(HACK_EXES_1) @SUID_EXES@ XSHM_OBJS = $(UTILS_BIN)/xshm.o $(UTILS_BIN)/aligned_malloc.o +DT = $(UTILS_BIN)/doubletime.o GRAB_OBJS = $(UTILS_BIN)/grabclient.o grab-ximage.o $(XSHM_OBJS) ANIM_OBJS = recanim-gl.o $(HACK_BIN)/ffmpeg-out.o + EXES = @GL_UTIL_EXES@ $(HACK_EXES) RETIRED_EXES = @RETIRED_GL_EXES@ @@ -265,6 +267,7 @@ HACK_OBJS = $(HACK_BIN)/screenhack.o $(HACK_BIN)/xlockmore.o \ $(UTILS_BIN)/usleep.o \ $(UTILS_BIN)/xmu.o \ $(UTILS_BIN)/yarandom.o \ + $(UTILS_BIN)/doubletime.o \ $(FPS_OBJS) $(JWZGLES_OBJS) $(HACK_GLSL_OBJS) @ANIM_OBJS@ HDRS = atlantis.h bubble3d.h buildlwo.h e_textures.h \ @@ -595,6 +598,7 @@ $(UTILS_BIN)/thread_util.o: $(UTILS_SRC)/thread_util.c $(UTILS_BIN)/spline.o: $(UTILS_SRC)/spline.c $(UTILS_BIN)/pow2.o: $(UTILS_SRC)/pow2.c $(UTILS_BIN)/font-retry.o: $(UTILS_SRC)/font-retry.c +$(UTILS_BIN)/easing.o: $(UTILS_SRC)/easing.c $(HACK_BIN)/screenhack.o: $(HACK_SRC)/screenhack.c $(HACK_BIN)/xlockmore.o: $(HACK_SRC)/xlockmore.c $(HACK_BIN)/fps.o: $(HACK_SRC)/fps.c @@ -713,7 +717,7 @@ PLANET_OBJS=sphere.o gllist.o timezones.o $(PNG) $(HACK_TRACK_OBJS) glplanet: glplanet.o $(PLANET_OBJS) $(CC_HACK) -o $@ $@.o $(PLANET_OBJS) $(PNG_LIBS) -DYMAXIOBJS=dymaxionmap-coords.o normals.o $(PLANET_OBJS) +DYMAXIOBJS=dymaxionmap-coords.o normals.o $(EASE) $(PLANET_OBJS) dymaxionmap: dymaxionmap.o $(DYMAXIOBJS) $(CC_HACK) -o $@ $@.o $(DYMAXIOBJS) $(PNG_LIBS) @@ -782,8 +786,8 @@ lavalite: lavalite.o $(LL_OBJS) queens: queens.o chessmodels.o $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o chessmodels.o $(HACK_TRACK_OBJS) $(HACK_LIBS) -endgame: endgame.o chessmodels.o $(HACK_TRACK_OBJS) - $(CC_HACK) -o $@ $@.o chessmodels.o $(HACK_TRACK_OBJS) $(HACK_LIBS) +endgame: endgame.o chessmodels.o $(EASE) $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o chessmodels.o $(EASE) $(HACK_TRACK_OBJS) $(HACK_LIBS) glblur: glblur.o $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) @@ -833,8 +837,10 @@ vigilance: $(CAM_OBJS) seccam_dxf:: ./dxf2gl.pl --smooth --layers seccam.dxf seccam.c -glslideshow: glslideshow.o $(HACK_GRAB_OBJS) - $(CC_HACK) -o $@ $@.o $(HACK_GRAB_OBJS) $(HACK_LIBS) +EASE = $(UTILS_BIN)/easing.o +SLIDE_OBJS = $(HACK_GRAB_OBJS) $(EASE) +glslideshow: glslideshow.o $(SLIDE_OBJS) + $(CC_HACK) -o $@ $@.o $(SLIDE_OBJS) $(HACK_LIBS) jigglypuff: jigglypuff.o $(PNG) $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o $(PNG) $(HACK_TRACK_OBJS) $(PNG_LIBS) @@ -928,8 +934,8 @@ moebiusgears: moebiusgears.o $(GEARS_OBJS) boing: boing.o normals.o $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS) -carousel: carousel.o $(HACK_TRACK_GRAB_OBJS) - $(CC_HACK) -o $@ $@.o $(HACK_TRACK_GRAB_OBJS) $(HACK_LIBS) +carousel: carousel.o $(EASE) $(HACK_TRACK_GRAB_OBJS) + $(CC_HACK) -o $@ $@.o $(EASE) $(HACK_TRACK_GRAB_OBJS) $(HACK_LIBS) fliptext: fliptext.o $(TEXT) $(HACK_OBJS) $(CC_HACK) -o $@ $@.o $(TEXT) $(HACK_OBJS) $(HACK_LIBS) $(TEXT_LIBS) @@ -1018,10 +1024,10 @@ CCUBE2=gllist.o $(HACK_TRACK_OBJS) companioncube: $(CCUBE1) $(CCUBE2) $(CC_HACK) -o $@ $(CCUBE1) $(CCUBE2) $(HACK_LIBS) -TBIT1=tronbit.o tronbit_idle1.o tronbit_idle2.o tronbit_no.o tronbit_yes.o -TBIT2=gllist.o $(HACK_TRACK_OBJS) -tronbit: $(TBIT1) $(TBIT2) - $(CC_HACK) -o $@ $(TBIT1) $(TBIT2) $(HACK_LIBS) +TBIT = tronbit.o tronbit_idle1.o tronbit_idle2.o tronbit_no.o tronbit_yes.o \ + gllist.o $(HACK_TRACK_OBJS) +tronbit: $(TBIT) + $(CC_HACK) -o $@ $(TBIT) $(HACK_LIBS) KALEIDOCYCLE_OBJS=kaleidocycle.o normals.o $(HACK_TRACK_OBJS) kaleidocycle: $(KALEIDOCYCLE_OBJS) @@ -1030,8 +1036,9 @@ kaleidocycle: $(KALEIDOCYCLE_OBJS) quasicrystal: quasicrystal.o $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) -unknownpleasures: unknownpleasures.o $(PNG) $(HACK_TRACK_OBJS) - $(CC_HACK) -o $@ $@.o $(PNG) $(HACK_TRACK_OBJS) $(HACK_LIBS) $(PNG_LIBS) +UNKOBJS = $(PNG) $(EASE) $(HACK_TRACK_OBJS) +unknownpleasures: unknownpleasures.o $(UNKOBJS) + $(CC_HACK) -o $@ $@.o $(UNKOBJS) $(HACK_LIBS) $(PNG_LIBS) geodesic: geodesic.o normals.o $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS) @@ -1056,21 +1063,21 @@ ES_OBJS=$(PNG) $(HACK_TRACK_OBJS) energystream: energystream.o $(ES_OBJS) $(CC_HACK) -o $@ $@.o $(ES_OBJS) $(PNG_LIBS) $(HACK_LIBS) -raverhoop: raverhoop.o $(HACK_TRACK_OBJS) - $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) +raverhoop: raverhoop.o $(EASE) $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(EASE) $(HACK_TRACK_OBJS) $(HACK_LIBS) -HSTAT_OBJS=sphere.o normals.o $(HACK_TRACK_OBJS) +HSTAT_OBJS=sphere.o normals.o $(EASE) $(HACK_TRACK_OBJS) hydrostat: hydrostat.o $(HSTAT_OBJS) $(CC_HACK) -o $@ $@.o $(HSTAT_OBJS) $(HACK_LIBS) discoball: discoball.o $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) -cubetwist: cubetwist.o $(HACK_TRACK_OBJS) - $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) +cubetwist: cubetwist.o $(HACK_TRACK_OBJS) $(EASE) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(EASE) $(HACK_LIBS) -cubestack: cubestack.o $(HACK_TRACK_OBJS) - $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) +cubestack: cubestack.o $(HACK_TRACK_OBJS) $(EASE) + $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(EASE) $(HACK_LIBS) splodesic: splodesic.o $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) @@ -1091,8 +1098,8 @@ razzledazzle: razzledazzle.o $(DAZ_OBJS) peepers: peepers.o normals.o $(PNG) $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o normals.o $(PNG) $(PNG_LIBS) $(HACK_TRACK_OBJS) $(HACK_LIBS) -crumbler: crumbler.o quickhull.o $(HACK_TRACK_OBJS) - $(CC_HACK) -o $@ $@.o quickhull.o $(HACK_TRACK_OBJS) $(HACK_LIBS) +crumbler: crumbler.o quickhull.o $(HACK_TRACK_OBJS) $(EASE) + $(CC_HACK) -o $@ $@.o quickhull.o $(HACK_TRACK_OBJS) $(EASE) $(HACK_LIBS) maze3d: maze3d.o $(PNG) $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o $(PNG) $(PNG_LIBS) $(HACK_TRACK_OBJS) $(HACK_LIBS) @@ -1110,8 +1117,8 @@ 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) +gibson: gibson.o $(PNG) $(EASE) $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(PNG) $(EASE) $(HACK_TRACK_OBJS) $(PNG_LIBS) covid19: covid19.o $(DB_OBJS) $(CC_HACK) -o $@ $@.o $(DB_OBJS) $(HACK_LIBS) @@ -1128,17 +1135,18 @@ headroom_dxf:: beats: beats.o sphere.o $(HACK_OBJS) $(CC_HACK) -o $@ $@.o sphere.o $(HACK_OBJS) $(HACK_LIBS) -mapscroller: mapscroller.o $(PNG) $(HACK_GRAB_OBJS) - $(CC_HACK) -o $@ $@.o $(PNG) $(HACK_GRAB_OBJS) $(PNG_LIBS) +mapscroller: mapscroller.o $(PNG) $(EASE) $(HACK_GRAB_OBJS) + $(CC_HACK) -o $@ $@.o $(PNG) $(EASE) $(HACK_GRAB_OBJS) $(PNG_LIBS) -SQOBJ = normals.o $(UTILS_BIN)/spline.o +SQOBJ = normals.o $(UTILS_BIN)/spline.o $(EASE) squirtorus: squirtorus.o $(SQOBJ) $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o $(SQOBJ) $(HACK_TRACK_OBJS) $(HACK_LIBS) -nakagin: nakagin.o $(HACK_TRACK_OBJS) - $(CC_HACK) -o $@ $@.o $(HACK_TRACK_OBJS) $(HACK_LIBS) +nakagin: nakagin.o $(EASE) $(HACK_TRACK_OBJS) + $(CC_HACK) -o $@ $@.o $(EASE) $(HACK_TRACK_OBJS) $(HACK_LIBS) -CHOBJS = gllist.o teeth_model.o normals.o sphere.o $(UTILS_BIN)/spline.o +CHOBJS = gllist.o teeth_model.o normals.o sphere.o $(UTILS_BIN)/spline.o \ + $(EASE) chompytower: chompytower.o $(CHOBJS) $(HACK_TRACK_OBJS) $(CC_HACK) -o $@ $@.o $(CHOBJS) $(HACK_TRACK_OBJS) $(HACK_LIBS) @@ -1155,7 +1163,7 @@ CUBOCT_OBJS=$(PNG) $(HACK_TRACK_OBJS) cubocteversion: cubocteversion.o $(CUBOCT_OBJS) $(CC_HACK) -o $@ $@.o $(CUBOCT_OBJS) $(HACK_LIBS) $(PNG_LIBS) -SKULLOOP_OBJS=gllist.o skull_model.o normals.o $(HACK_TRACK_OBJS) +SKULLOOP_OBJS=gllist.o skull_model.o normals.o $(EASE) $(HACK_TRACK_OBJS) skulloop: skulloop.o $(SKULLOOP_OBJS) $(CC_HACK) -o $@ $@.o $(SKULLOOP_OBJS) $(HACK_LIBS) @@ -1200,7 +1208,7 @@ klondike: klondike.o $(KLONDIKE_OBJS) dumpster_dxf:: ./dxf2gl.pl --smooth --layers --normalize dumpster.dxf dumpster_model.c -DUMPSTERFIRE=dumpsterfire.o dumpster_model.o gllist.o $(HACK_TRACK_OBJS) +DUMPSTERFIRE=dumpsterfire.o dumpster_model.o gllist.o $(EASE) $(HACK_TRACK_OBJS) dumpsterfire: $(DUMPSTERFIRE) $(CC_HACK) -o $@ $(DUMPSTERFIRE) $(HACK_LIBS) @@ -1519,6 +1527,7 @@ carousel.o: $(srcdir)/rotator.h carousel.o: $(HACK_SRC)/screenhackI.h carousel.o: $(srcdir)/texfont.h carousel.o: $(UTILS_SRC)/colors.h +carousel.o: $(UTILS_SRC)/easing.h carousel.o: $(UTILS_SRC)/erase.h carousel.o: $(UTILS_SRC)/font-retry.h carousel.o: $(UTILS_SRC)/grabclient.h @@ -1554,6 +1563,8 @@ chompytower.o: $(srcdir)/rotator.h chompytower.o: $(HACK_SRC)/screenhackI.h chompytower.o: $(srcdir)/sphere.h chompytower.o: $(UTILS_SRC)/colors.h +chompytower.o: $(UTILS_SRC)/doubletime.h +chompytower.o: $(UTILS_SRC)/easing.h chompytower.o: $(UTILS_SRC)/erase.h chompytower.o: $(UTILS_SRC)/font-retry.h chompytower.o: $(UTILS_SRC)/grabclient.h @@ -1828,6 +1839,7 @@ crumbler.o: $(HACK_SRC)/recanim.h crumbler.o: $(srcdir)/rotator.h crumbler.o: $(HACK_SRC)/screenhackI.h crumbler.o: $(UTILS_SRC)/colors.h +crumbler.o: $(UTILS_SRC)/easing.h crumbler.o: $(UTILS_SRC)/erase.h crumbler.o: $(UTILS_SRC)/font-retry.h crumbler.o: $(UTILS_SRC)/grabclient.h @@ -1881,6 +1893,7 @@ cubestack.o: $(HACK_SRC)/recanim.h cubestack.o: $(srcdir)/rotator.h cubestack.o: $(HACK_SRC)/screenhackI.h cubestack.o: $(UTILS_SRC)/colors.h +cubestack.o: $(UTILS_SRC)/easing.h cubestack.o: $(UTILS_SRC)/erase.h cubestack.o: $(UTILS_SRC)/font-retry.h cubestack.o: $(UTILS_SRC)/grabclient.h @@ -1918,6 +1931,7 @@ cubetwist.o: $(HACK_SRC)/recanim.h cubetwist.o: $(srcdir)/rotator.h cubetwist.o: $(HACK_SRC)/screenhackI.h cubetwist.o: $(UTILS_SRC)/colors.h +cubetwist.o: $(UTILS_SRC)/easing.h cubetwist.o: $(UTILS_SRC)/erase.h cubetwist.o: $(UTILS_SRC)/font-retry.h cubetwist.o: $(UTILS_SRC)/grabclient.h @@ -2087,6 +2101,7 @@ dumpsterfire.o: $(HACK_SRC)/recanim.h dumpsterfire.o: $(srcdir)/rotator.h dumpsterfire.o: $(HACK_SRC)/screenhackI.h dumpsterfire.o: $(UTILS_SRC)/colors.h +dumpsterfire.o: $(UTILS_SRC)/easing.h dumpsterfire.o: $(UTILS_SRC)/erase.h dumpsterfire.o: $(UTILS_SRC)/font-retry.h dumpsterfire.o: $(UTILS_SRC)/grabclient.h @@ -2131,6 +2146,8 @@ dymaxionmap.o: $(HACK_SRC)/screenhackI.h dymaxionmap.o: $(srcdir)/sphere.h dymaxionmap.o: $(srcdir)/texfont.h dymaxionmap.o: $(UTILS_SRC)/colors.h +dymaxionmap.o: $(UTILS_SRC)/doubletime.h +dymaxionmap.o: $(UTILS_SRC)/easing.h dymaxionmap.o: $(UTILS_SRC)/erase.h dymaxionmap.o: $(UTILS_SRC)/font-retry.h dymaxionmap.o: $(UTILS_SRC)/grabclient.h @@ -2150,7 +2167,9 @@ endgame.o: $(HACK_SRC)/fps.h endgame.o: $(srcdir)/gltrackball.h endgame.o: $(HACK_SRC)/recanim.h endgame.o: $(HACK_SRC)/screenhackI.h +endgame.o: $(srcdir)/texfont.h endgame.o: $(UTILS_SRC)/colors.h +endgame.o: $(UTILS_SRC)/easing.h endgame.o: $(UTILS_SRC)/erase.h endgame.o: $(UTILS_SRC)/font-retry.h endgame.o: $(UTILS_SRC)/grabclient.h @@ -2209,6 +2228,7 @@ esper.o: $(HACK_SRC)/recanim.h esper.o: $(HACK_SRC)/screenhackI.h esper.o: $(srcdir)/texfont.h esper.o: $(UTILS_SRC)/colors.h +esper.o: $(UTILS_SRC)/doubletime.h esper.o: $(UTILS_SRC)/erase.h esper.o: $(UTILS_SRC)/font-retry.h esper.o: $(UTILS_SRC)/grabclient.h @@ -2643,6 +2663,7 @@ 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)/easing.h gibson.o: $(UTILS_SRC)/erase.h gibson.o: $(UTILS_SRC)/font-retry.h gibson.o: $(UTILS_SRC)/grabclient.h @@ -2732,6 +2753,7 @@ glhanoi.o: $(HACK_SRC)/recanim.h glhanoi.o: $(srcdir)/rotator.h glhanoi.o: $(HACK_SRC)/screenhackI.h glhanoi.o: $(UTILS_SRC)/colors.h +glhanoi.o: $(UTILS_SRC)/doubletime.h glhanoi.o: $(UTILS_SRC)/erase.h glhanoi.o: $(UTILS_SRC)/font-retry.h glhanoi.o: $(UTILS_SRC)/grabclient.h @@ -2867,6 +2889,8 @@ glslideshow.o: $(HACK_SRC)/recanim.h glslideshow.o: $(HACK_SRC)/screenhackI.h glslideshow.o: $(srcdir)/texfont.h glslideshow.o: $(UTILS_SRC)/colors.h +glslideshow.o: $(UTILS_SRC)/doubletime.h +glslideshow.o: $(UTILS_SRC)/easing.h glslideshow.o: $(UTILS_SRC)/erase.h glslideshow.o: $(UTILS_SRC)/font-retry.h glslideshow.o: $(UTILS_SRC)/grabclient.h @@ -2983,6 +3007,7 @@ grab-ximage.o: $(srcdir)/grab-ximage.h grab-ximage.o: $(HACK_SRC)/recanim.h grab-ximage.o: $(HACK_SRC)/screenhackI.h grab-ximage.o: $(UTILS_SRC)/colors.h +grab-ximage.o: $(UTILS_SRC)/doubletime.h grab-ximage.o: $(UTILS_SRC)/erase.h grab-ximage.o: $(UTILS_SRC)/font-retry.h grab-ximage.o: $(UTILS_SRC)/grabclient.h @@ -3039,6 +3064,7 @@ handsy.o: $(HACK_SRC)/screenhackI.h handsy.o: $(srcdir)/sphere.h handsy.o: $(srcdir)/tube.h handsy.o: $(UTILS_SRC)/colors.h +handsy.o: $(UTILS_SRC)/doubletime.h handsy.o: $(UTILS_SRC)/erase.h handsy.o: $(UTILS_SRC)/font-retry.h handsy.o: $(UTILS_SRC)/grabclient.h @@ -3207,6 +3233,7 @@ hydrostat.o: $(HACK_SRC)/recanim.h hydrostat.o: $(HACK_SRC)/screenhackI.h hydrostat.o: $(srcdir)/sphere.h hydrostat.o: $(UTILS_SRC)/colors.h +hydrostat.o: $(UTILS_SRC)/easing.h hydrostat.o: $(UTILS_SRC)/erase.h hydrostat.o: $(UTILS_SRC)/font-retry.h hydrostat.o: $(UTILS_SRC)/grabclient.h @@ -3575,6 +3602,7 @@ mapscroller.o: $(HACK_SRC)/recanim.h mapscroller.o: $(HACK_SRC)/screenhackI.h mapscroller.o: $(srcdir)/texfont.h mapscroller.o: $(UTILS_SRC)/colors.h +mapscroller.o: $(UTILS_SRC)/easing.h mapscroller.o: $(UTILS_SRC)/erase.h mapscroller.o: $(UTILS_SRC)/font-retry.h mapscroller.o: $(UTILS_SRC)/grabclient.h @@ -3650,6 +3678,7 @@ mirrorblob.o: $(srcdir)/grab-ximage.h mirrorblob.o: $(HACK_SRC)/recanim.h mirrorblob.o: $(HACK_SRC)/screenhackI.h mirrorblob.o: $(UTILS_SRC)/colors.h +mirrorblob.o: $(UTILS_SRC)/doubletime.h mirrorblob.o: $(UTILS_SRC)/erase.h mirrorblob.o: $(UTILS_SRC)/font-retry.h mirrorblob.o: $(UTILS_SRC)/grabclient.h @@ -3747,6 +3776,8 @@ nakagin.o: $(HACK_SRC)/recanim.h nakagin.o: $(srcdir)/rotator.h nakagin.o: $(HACK_SRC)/screenhackI.h nakagin.o: $(UTILS_SRC)/colors.h +nakagin.o: $(UTILS_SRC)/doubletime.h +nakagin.o: $(UTILS_SRC)/easing.h nakagin.o: $(UTILS_SRC)/erase.h nakagin.o: $(UTILS_SRC)/font-retry.h nakagin.o: $(UTILS_SRC)/grabclient.h @@ -4074,6 +4105,7 @@ raverhoop.o: $(HACK_SRC)/recanim.h raverhoop.o: $(srcdir)/rotator.h raverhoop.o: $(HACK_SRC)/screenhackI.h raverhoop.o: $(UTILS_SRC)/colors.h +raverhoop.o: $(UTILS_SRC)/easing.h raverhoop.o: $(UTILS_SRC)/erase.h raverhoop.o: $(UTILS_SRC)/font-retry.h raverhoop.o: $(UTILS_SRC)/grabclient.h @@ -4415,6 +4447,7 @@ skulloop.o: $(HACK_SRC)/recanim.h skulloop.o: $(HACK_SRC)/screenhackI.h skulloop.o: $(srcdir)/texfont.h skulloop.o: $(UTILS_SRC)/colors.h +skulloop.o: $(UTILS_SRC)/easing.h skulloop.o: $(UTILS_SRC)/erase.h skulloop.o: $(UTILS_SRC)/font-retry.h skulloop.o: $(UTILS_SRC)/grabclient.h @@ -4455,6 +4488,7 @@ sonar-icmp.o: $(srcdir)/sonar.h sonar-icmp.o: $(UTILS_SRC)/aligned_malloc.h sonar-icmp.o: $(UTILS_SRC)/async_netdb.h sonar-icmp.o: $(UTILS_SRC)/colors.h +sonar-icmp.o: $(UTILS_SRC)/doubletime.h sonar-icmp.o: $(UTILS_SRC)/font-retry.h sonar-icmp.o: $(UTILS_SRC)/grabclient.h sonar-icmp.o: $(UTILS_SRC)/hsv.h @@ -4475,6 +4509,7 @@ sonar.o: $(srcdir)/sonar.h sonar.o: $(srcdir)/texfont.h sonar.o: $(UTILS_SRC)/aligned_malloc.h sonar.o: $(UTILS_SRC)/colors.h +sonar.o: $(UTILS_SRC)/doubletime.h sonar.o: $(UTILS_SRC)/erase.h sonar.o: $(UTILS_SRC)/font-retry.h sonar.o: $(UTILS_SRC)/grabclient.h @@ -4695,6 +4730,7 @@ squirtorus.o: $(srcdir)/normals.h squirtorus.o: $(HACK_SRC)/recanim.h squirtorus.o: $(HACK_SRC)/screenhackI.h squirtorus.o: $(UTILS_SRC)/colors.h +squirtorus.o: $(UTILS_SRC)/easing.h squirtorus.o: $(UTILS_SRC)/erase.h squirtorus.o: $(UTILS_SRC)/font-retry.h squirtorus.o: $(UTILS_SRC)/grabclient.h @@ -5204,6 +5240,7 @@ tronbit.o: $(srcdir)/rotator.h tronbit.o: $(HACK_SRC)/screenhackI.h tronbit.o: $(srcdir)/sphere.h tronbit.o: $(UTILS_SRC)/colors.h +tronbit.o: $(UTILS_SRC)/doubletime.h tronbit.o: $(UTILS_SRC)/erase.h tronbit.o: $(UTILS_SRC)/font-retry.h tronbit.o: $(UTILS_SRC)/grabclient.h @@ -5286,6 +5323,8 @@ unknownpleasures.o: $(srcdir)/grab-ximage.h unknownpleasures.o: $(HACK_SRC)/recanim.h unknownpleasures.o: $(HACK_SRC)/screenhackI.h unknownpleasures.o: $(UTILS_SRC)/colors.h +unknownpleasures.o: $(UTILS_SRC)/doubletime.h +unknownpleasures.o: $(UTILS_SRC)/easing.h unknownpleasures.o: $(UTILS_SRC)/erase.h unknownpleasures.o: $(UTILS_SRC)/font-retry.h unknownpleasures.o: $(UTILS_SRC)/grabclient.h @@ -5323,6 +5362,7 @@ voronoi.o: $(HACK_SRC)/fps.h voronoi.o: $(HACK_SRC)/recanim.h voronoi.o: $(HACK_SRC)/screenhackI.h voronoi.o: $(UTILS_SRC)/colors.h +voronoi.o: $(UTILS_SRC)/doubletime.h voronoi.o: $(UTILS_SRC)/erase.h voronoi.o: $(UTILS_SRC)/font-retry.h voronoi.o: $(UTILS_SRC)/grabclient.h diff --git a/hacks/glx/carousel.c b/hacks/glx/carousel.c index d265e6f80..901cda2f1 100644 --- a/hacks/glx/carousel.c +++ b/hacks/glx/carousel.c @@ -1,4 +1,4 @@ -/* carousel, Copyright © 2005-2023 Jamie Zawinski +/* carousel, Copyright © 2005-2025 Jamie Zawinski * Loads a sequence of images and rotates them around. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -30,6 +30,7 @@ # define release_carousel 0 # include "xlockmore.h" +# include "easing.h" #ifdef USE_GL @@ -63,7 +64,7 @@ typedef struct { } rect; typedef enum { EARLY, NORMAL, LOADING, OUT, IN, DEAD } fade_mode; -static int fade_ticks = 60; +static int fade_ticks = 30 * 5; typedef struct { char *title; /* the filename of this image */ @@ -758,8 +759,10 @@ draw_frame (ModeInfo *mi, image_frame *frame, time_t now, Bool body_p) ? frame->mode_tick / (fade_ticks / speed) : (((fade_ticks / speed) - frame->mode_tick + 1) / (fade_ticks / speed))); - t = 5 * (1 - t); + t = 1-t; + t = ease (EASE_IN_OUT_BACK, t); if (frame->from_top_p) t = -t; + t *= 5; glTranslatef (0, t, 0); } diff --git a/hacks/glx/chompytower.c b/hacks/glx/chompytower.c index 057f09480..73da06f09 100644 --- a/hacks/glx/chompytower.c +++ b/hacks/glx/chompytower.c @@ -1,4 +1,4 @@ -/* chompytower, Copyright © 2022 Jamie Zawinski +/* chompytower, Copyright © 2022-2025 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 @@ -43,6 +43,8 @@ #include "spline.h" #include "gltrackball.h" #include "gllist.h" +#include "easing.h" +#include "doubletime.h" #include extern const struct gllist @@ -152,21 +154,6 @@ ENTRYPOINT ModeSpecOpt chompytower_opts = { #define SPLINE_SCALE 1000 #define FUNHOLE_HEIGHT 0.2 -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static void parse_color (ModeInfo *mi, char *key, GLfloat color[4]) { @@ -896,25 +883,6 @@ draw_component (ModeInfo *mi, int i) } -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; -} - - static int draw_funhole (ModeInfo *mi, slice *s, Bool shadow_p) { @@ -944,10 +912,10 @@ draw_funhole (ModeInfo *mi, slice *s, Bool shadow_p) switch (s->funhole.state) { case HIDDEN: dist = 0; break; - case EXTENDING: dist *= ease_ratio (s->funhole.ratio); break; - case RETRACTING: dist *= ease_ratio (1 - s->funhole.ratio); break; - case OPENING: tilt = ease_ratio (s->funhole.ratio); break; - case CLOSING: tilt = ease_ratio (1 - s->funhole.ratio); break; + case EXTENDING: dist *= ease(EASE_IN_OUT_SINE, s->funhole.ratio); break; + case RETRACTING: dist *= ease(EASE_IN_OUT_SINE, 1-s->funhole.ratio); break; + case OPENING: tilt = ease(EASE_IN_OUT_SINE, s->funhole.ratio); break; + case CLOSING: tilt = ease(EASE_IN_OUT_SINE, 1-s->funhole.ratio); break; case OPEN: tilt = 1; break; case CLOSED: tilt = 0; break; default: abort(); break; diff --git a/hacks/glx/crumbler.c b/hacks/glx/crumbler.c index fccee8de6..132ecb673 100644 --- a/hacks/glx/crumbler.c +++ b/hacks/glx/crumbler.c @@ -1,4 +1,4 @@ -/* crumbler, Copyright (c) 2018 Jamie Zawinski +/* crumbler, Copyright © 2018-2025 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 @@ -21,6 +21,7 @@ #include "rotator.h" #include "quickhull.h" #include "gltrackball.h" +#include "easing.h" #include #ifdef USE_GL /* whole file */ @@ -563,25 +564,6 @@ tick_crumbler (ModeInfo *mi) } -static GLfloat -ease_fn (GLfloat r) -{ - return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */ -} - - -static GLfloat -ease_ratio (GLfloat r) -{ - GLfloat ease = 0.35; - if (r <= 0) return 0; - else if (r >= 1) return 1; - else if (r <= ease) return ease * ease_fn (r / ease); - else if (r > 1-ease) return 1 - ease * ease_fn ((1 - r) / ease); - else return r; -} - - /* Window management, etc */ ENTRYPOINT void @@ -840,7 +822,7 @@ draw_crumbler (ModeInfo *mi) switch (bp->state) { case FLEE: { - GLfloat r = ease_ratio (bp->tick); + GLfloat r = ease (EASE_IN_OUT_SINE, bp->tick); /* Move everybody toward the origin, so that chunk #0 ends up centered there. */ glTranslatef (-r * c->mid.x, @@ -865,7 +847,7 @@ draw_crumbler (ModeInfo *mi) GLfloat Z = (c->max.z - c->min.z); GLfloat size0 = MAX(X, MAX(Y, Z)); GLfloat size1 = 1.0; - GLfloat r = 1 - ease_ratio (bp->tick); + GLfloat r = 1 - ease (EASE_IN_OUT_SINE, bp->tick); GLfloat s = 1 / (size0 + r * (size1 - size0)); glScalef (s, s, s); } @@ -885,8 +867,8 @@ draw_crumbler (ModeInfo *mi) GLfloat s; /* alpha = 1 - bp->tick; */ alpha = 1; - /* s = 0.7 + (0.3 * ease_ratio (1-bp->tick)); */ - s = 2 * ease_ratio ((1-bp->tick) / 2); + /* s = 0.7 + (0.3 * ease (EASE_IN_OUT_SINE, 1-bp->tick)); */ + s = 2 * ease (EASE_IN_OUT_SINE, (1-bp->tick) / 2); s *= 1.01; glScalef (s, s, s); draw_chunk (mi, bp->ghost, alpha); diff --git a/hacks/glx/cubestack.c b/hacks/glx/cubestack.c index ef62ab414..e38741374 100644 --- a/hacks/glx/cubestack.c +++ b/hacks/glx/cubestack.c @@ -1,4 +1,4 @@ -/* cubestack, Copyright (c) 2016 Jamie Zawinski +/* cubestack, Copyright © 2016-2025 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 @@ -20,6 +20,7 @@ #include "colors.h" #include "rotator.h" #include "gltrackball.h" +#include "easing.h" #include #ifdef USE_GL /* whole file */ @@ -120,25 +121,6 @@ draw_face (ModeInfo *mi) } -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; -} - - static int draw_cube_1 (ModeInfo *mi, GLfloat state, GLfloat color[4], Bool bottom_p) { @@ -147,7 +129,7 @@ draw_cube_1 (ModeInfo *mi, GLfloat state, GLfloat color[4], Bool bottom_p) GLfloat r = state - istate; GLfloat a = color[3]; - r = ease_ratio (r); + r = ease (EASE_IN_OUT_SINE, r); # define COLORIZE(R) \ color[3] = a * R; \ diff --git a/hacks/glx/cubetwist.c b/hacks/glx/cubetwist.c index eed1901c7..fdaea8ad0 100644 --- a/hacks/glx/cubetwist.c +++ b/hacks/glx/cubetwist.c @@ -1,4 +1,4 @@ -/* cubetwist, Copyright (c) 2016-2017 Jamie Zawinski +/* cubetwist, Copyright © 2016-2025 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 @@ -20,6 +20,7 @@ #include "normals.h" #include "rotator.h" #include "gltrackball.h" +#include "easing.h" #include #ifdef USE_GL /* whole file */ @@ -211,25 +212,6 @@ make_cubes (ModeInfo *mi) } -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; -} - - static void tick_oscillators (ModeInfo *mi) { @@ -245,7 +227,7 @@ tick_oscillators (ModeInfo *mi) if (a->ratio > 1) a->ratio = 1; - *a->var = a->from + (a->to - a->from) * ease_ratio (a->ratio); + *a->var = a->from + (a->to - a->from) * ease(EASE_IN_OUT_SINE, a->ratio); if (a->ratio < 1) /* mid cycle */ prev = a; diff --git a/hacks/glx/dumpsterfire.c b/hacks/glx/dumpsterfire.c index c0392f4d0..39edc722c 100644 --- a/hacks/glx/dumpsterfire.c +++ b/hacks/glx/dumpsterfire.c @@ -34,6 +34,7 @@ #include "rotator.h" #include "gltrackball.h" #include "gllist.h" +#include "easing.h" #include #define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) @@ -638,26 +639,6 @@ draw_component (ModeInfo *mi, int i, Bool half_p) } -static double -easeOutBounce (double i) -{ - double n1 = 7.5625; - double d1 = 2.75; - if (i < 1 / d1) { - return n1 * i * i; - } else if (i < 2 / d1) { - i -= (1.5 / d1); - return n1 * i * i + 0.75; - } else if (i < 2.5 / d1) { - i -= (2.25 / d1); - return n1 * i * i + 0.9375; - } else { - i -= (2.625 / d1); - return n1 * i * i + 0.984375; - } -} - - static void tick_dumpster (ModeInfo *mi) { @@ -735,7 +716,7 @@ draw_box (ModeInfo *mi) switch (bp->state) { case DROP: bp->pos.x = bp->pos.y = 0; - bp->pos.z = (1 - easeOutBounce (bp->tick)) * 3; + bp->pos.z = (1 - ease (EASE_OUT_BOUNCE, (bp->tick))) * 3; break; case OPEN: bp->lid_angle[(bp->lid_angle[0] == 0.0 ? 1 : 0)] = bp->tick + 0.0001; @@ -767,8 +748,8 @@ draw_box (ModeInfo *mi) const GLfloat deg = 115; const XYZ off = { 0, 0.63, -0.25 }; double a2 = (bp->state == CLOSE - ? 1 - easeOutBounce (1 - bp->lid_angle[i]) - : easeOutBounce ( bp->lid_angle[i])); + ? 1 - ease (EASE_OUT_BOUNCE, (1 - bp->lid_angle[i])) + : ease (EASE_OUT_BOUNCE, ( bp->lid_angle[i]))); glPushMatrix(); glTranslatef (off.x, off.y, off.z); @@ -818,6 +799,8 @@ draw_dumpster (ModeInfo *mi) /* glRotatef (z * 360, 0.0, 0.0, 1.0); */ } + glRotatef (current_device_rotation(), 0, 0, 1); + mi->polygon_count = 0; glTranslatef (0, -6, 0); diff --git a/hacks/glx/dymaxionmap.c b/hacks/glx/dymaxionmap.c index 35e1c1504..37816b146 100644 --- a/hacks/glx/dymaxionmap.c +++ b/hacks/glx/dymaxionmap.c @@ -1,5 +1,5 @@ /* dymaxionmap --- Buckminster Fuller's unwrapped icosahedral globe. - * Copyright © 2016-2022 Jamie Zawinski. + * Copyright © 2016-2025 Jamie Zawinski. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, @@ -31,6 +31,8 @@ #include "sphere.h" #include "normals.h" +#include "easing.h" +#include "doubletime.h" #include "texfont.h" #include "dymaxionmap-coords.h" @@ -156,21 +158,6 @@ typedef struct { static planetstruct *planets = NULL; -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - /* Draw faint latitude and longitude lines into the RGBA XImage. */ static void @@ -1494,25 +1481,6 @@ init_planet (ModeInfo * mi) } -static GLfloat -ease_fn (GLfloat r) -{ - return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */ -} - - -static GLfloat -ease_ratio (GLfloat r) -{ - GLfloat ease = 0.35; - if (r <= 0) return 0; - else if (r >= 1) return 1; - else if (r <= ease) return ease * ease_fn (r / ease); - else if (r > 1-ease) return 1 - ease * ease_fn ((1 - r) / ease); - else return r; -} - - ENTRYPOINT void draw_planet (ModeInfo * mi) { @@ -1696,7 +1664,7 @@ draw_planet (ModeInfo * mi) case STEL_IN: fold_ratio = 1; stel_ratio = gp->ratio; break; case STEL_OUT: fold_ratio = 1; stel_ratio = 1 - gp->ratio; break; case STARTUP: /* Tilt in from flat */ - glRotatef (-90 * ease_ratio (1 - gp->ratio), 1, 0, 0); + glRotatef (-90 * ease (EASE_IN_OUT_SINE, 1 - gp->ratio), 1, 0, 0); break; default: break; @@ -1704,7 +1672,7 @@ draw_planet (ModeInfo * mi) # ifdef HAVE_MOBILE /* Enlarge the icosahedron a bit to make it more visible */ { - GLfloat s = 1 + 1.3 * ease_ratio (fold_ratio); + GLfloat s = 1 + 1.3 * ease (EASE_IN_OUT_SINE, fold_ratio); glScalef (s, s, s); } # endif @@ -1712,11 +1680,13 @@ draw_planet (ModeInfo * mi) if (gp->state == SPIN) { align_axis (mi, 0); - glRotatef (ease_ratio (gp->ratio) * 360 * 3, 0, 0, 1); + glRotatef (ease (EASE_IN_OUT_SINE, gp->ratio) * 360 * 3, 0, 0, 1); align_axis (mi, 1); } - draw_triangles (mi, ease_ratio (fold_ratio), ease_ratio (stel_ratio)); + draw_triangles (mi, + ease (EASE_IN_OUT_SINE, fold_ratio), + ease (EASE_IN_OUT_SINE, stel_ratio)); if (gp->state == AXIS) draw_axis(mi); diff --git a/hacks/glx/esper.c b/hacks/glx/esper.c index 1302cac49..b557908c4 100644 --- a/hacks/glx/esper.c +++ b/hacks/glx/esper.c @@ -1,4 +1,4 @@ -/* esper, Copyright © 2017-2021 Jamie Zawinski +/* esper, Copyright © 2017-2025 Jamie Zawinski * Enhance 224 to 176. Pull out track right. Center in pull back. * Pull back. Wait a minute. Go right. Stop. Enhance 57 19. Track 45 left. * Gimme a hardcopy right there. @@ -164,6 +164,7 @@ #include "grab-ximage.h" #include "texfont.h" +#include "doubletime.h" #ifdef HAVE_XSHM_EXTENSION # include "xshm.h" /* to get */ @@ -291,22 +292,6 @@ static argtype vars[] = { ENTRYPOINT ModeSpecOpt esper_opts = {countof(opts), opts, countof(vars), vars, NULL}; -/* Returns the current time in seconds as a double. - */ -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - static const char * state_name (anim_state s) { diff --git a/hacks/glx/gibson.c b/hacks/glx/gibson.c index e90d8d25f..77ce9adc6 100644 --- a/hacks/glx/gibson.c +++ b/hacks/glx/gibson.c @@ -1,4 +1,4 @@ -/* gibson, Copyright (c) 2020-2021 Jamie Zawinski +/* gibson, Copyright © 2020-2025 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 @@ -31,6 +31,7 @@ #include "colors.h" #include "rotator.h" #include "texfont.h" +#include "easing.h" #include #ifdef USE_GL /* whole file */ @@ -408,25 +409,6 @@ cmp_towers (const void *aa, const void *bb) } -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. */ @@ -1253,7 +1235,8 @@ draw_gibson (ModeInfo *mi) { tower *t = &bp->towers[i]; glPushMatrix(); - glTranslatef (t->x, t->y-1, -grid_height * ease_ratio (1 - t->h)); + glTranslatef (t->x, t->y-1, + -grid_height * ease (EASE_IN_OUT_SINE, 1 - t->h)); glCallList (bp->tower_dlist); mi->polygon_count += bp->tower_polys; diff --git a/hacks/glx/glhanoi.c b/hacks/glx/glhanoi.c index b54428398..415723ae3 100644 --- a/hacks/glx/glhanoi.c +++ b/hacks/glx/glhanoi.c @@ -15,6 +15,7 @@ #include #include "rotator.h" +#include "doubletime.h" #define DEF_LIGHT "True" #define DEF_FOG "False" @@ -67,17 +68,6 @@ enum { typedef struct timeval glhtime; -static double getTime(void) -{ - struct timeval t; -#ifdef GETTIMEOFDAY_TWO_ARGS - gettimeofday(&t, NULL); -#else /* !GETTIMEOFDAY_TWO_ARGS */ - gettimeofday(&t); -#endif /* !GETTIMEOFDAY_TWO_ARGS */ - return t.tv_sec + t.tv_usec / 1000000.0; -} - typedef enum { START, MOVE_DISK, @@ -614,7 +604,7 @@ static void enQTrail(glhcfg *glhanoi, GLfloat *posn) { if (glhanoi->trailQSize && glhanoi->state != MONEY_SHOT) { TrailPoint *tp = &(glhanoi->trailQ[glhanoi->trailQBack]); - double t = getTime(); + double t = double_time(); tp->position[0] = posn[0]; tp->position[1] = posn[1] + glhanoi->diskHeight; @@ -702,7 +692,7 @@ static void updateView(glhcfg *glhanoi) static void changeState(glhcfg *glhanoi, State state) { glhanoi->state = state; - glhanoi->startTime = getTime(); + glhanoi->startTime = double_time(); } static Bool finishedHanoi(glhcfg *glhanoi) { @@ -714,7 +704,7 @@ static Bool finishedHanoi(glhcfg *glhanoi) { static void update_glhanoi(glhcfg *glhanoi) { - double t = getTime() - glhanoi->startTime; + double t = double_time() - glhanoi->startTime; int i; Bool done; @@ -1824,7 +1814,7 @@ static int drawTrails1(glhcfg *glhanoi, double t, double thickness, double alpha static int drawTrails(glhcfg *glhanoi) { int lines = 0; - double t = getTime(); + double t = double_time(); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/hacks/glx/glslideshow.c b/hacks/glx/glslideshow.c index 24930c8f9..3ec34b66f 100644 --- a/hacks/glx/glslideshow.c +++ b/hacks/glx/glslideshow.c @@ -77,6 +77,8 @@ #include "grab-ximage.h" #include "texfont.h" +#include "easing.h" +#include "doubletime.h" # ifndef HAVE_JWXYZ # include /* for XrmDatabase in -verbose mode */ @@ -231,23 +233,6 @@ blurb (void) } -/* Returns the current time in seconds as a double. - */ -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static void image_loaded_cb (const char *filename, XRectangle *geom, int image_width, int image_height, int texture_width, int texture_height, diff --git a/hacks/glx/grab-ximage.c b/hacks/glx/grab-ximage.c index defefda8d..a63b7333c 100644 --- a/hacks/glx/grab-ximage.c +++ b/hacks/glx/grab-ximage.c @@ -1,5 +1,5 @@ /* grab-ximage.c --- grab the screen to an XImage for use with OpenGL. - * xscreensaver, Copyright © 2001-2022 Jamie Zawinski + * xscreensaver, Copyright © 2001-2025 Jamie Zawinski * * Modified by Richard Weeks Copyright (c) 2020 * @@ -18,6 +18,7 @@ #include "pow2.h" #include "visual.h" #include "xshm.h" +#include "doubletime.h" #include #include @@ -486,23 +487,6 @@ struct texture_loader_t { }; -/* Returns the current time in seconds as a double. - */ -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - /* Loads the given XImage into GL's texture memory. The image may be of any size. If mipmap_p is true, then make mipmaps instead of just a single texture. diff --git a/hacks/glx/handsy.c b/hacks/glx/handsy.c index f03c70843..2cf1b8e53 100644 --- a/hacks/glx/handsy.c +++ b/hacks/glx/handsy.c @@ -1,4 +1,4 @@ -/* handsy, Copyright © 2018-2023 Jamie Zawinski +/* handsy, Copyright © 2018-2025 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 @@ -24,6 +24,7 @@ #include "rotator.h" #include "gltrackball.h" #include "gllist.h" +#include "doubletime.h" #include #ifdef USE_GL /* whole file */ @@ -195,23 +196,6 @@ static argtype vars[] = { ENTRYPOINT ModeSpecOpt hands_opts = {countof(opts), opts, countof(vars), vars, NULL}; -/* Returns the current time in seconds as a double. - */ -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static double constrain_joint (double v, double min, double max) { diff --git a/hacks/glx/hydrostat.c b/hacks/glx/hydrostat.c index 6ff00e843..836d22a94 100644 --- a/hacks/glx/hydrostat.c +++ b/hacks/glx/hydrostat.c @@ -1,5 +1,4 @@ -/* hydrostat, Copyright (C) 2012 by Justin Windle - * Copyright (c) 2016 Jamie Zawinski +/* hydrostat, Copyright © 2012-2025 Jamie Zawinski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,6 +38,7 @@ #include "colors.h" #include "sphere.h" #include "normals.h" +#include "easing.h" #include "gltrackball.h" #include @@ -217,27 +217,6 @@ move_tentacle (squid *sq, tentacle *t) } -static GLfloat -ease_fn (GLfloat r) -{ - return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */ -} - - -/* Squirty motion: fast acceleration, then fade. */ -static GLfloat -ease_ratio (GLfloat r) -{ - GLfloat ease = 0.05; - GLfloat ease2 = 1-ease; - if (r <= 0) r = 0; - else if (r >= 1) r = 1; - else if (r <= ease) r = ease * ease_fn (r / ease); - else r = 1 - ease2 * ease_fn ((1 - r) / ease2); - return r; -} - - static void move_squid (ModeInfo *mi, squid *sq) { @@ -263,7 +242,7 @@ move_squid (ModeInfo *mi, squid *sq) sq->to.z = 250 - frand(500); } - r = sq->ratio > 0 ? ease_ratio (sq->ratio) : 0; + r = sq->ratio > 0 ? ease (EASE_IN_OUT_SINE, sq->ratio) : 0; sq->pos.x = sq->from.x + r * (sq->to.x - sq->from.x); sq->pos.y = sq->from.y + r * (sq->to.y - sq->from.y); sq->pos.z = sq->from.z + r * (sq->to.z - sq->from.z); diff --git a/hacks/glx/mapscroller.c b/hacks/glx/mapscroller.c index 659ae14a9..781b9ef9f 100644 --- a/hacks/glx/mapscroller.c +++ b/hacks/glx/mapscroller.c @@ -38,6 +38,7 @@ #include "xlockmore.h" #include "ximage-loader.h" #include "texfont.h" +#include "easing.h" #include "../images/gen/oceantiles_12_png.h" #ifdef USE_GL /* whole file */ @@ -1165,25 +1166,6 @@ init_map (ModeInfo *mi) } -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; -} - - ENTRYPOINT void draw_map (ModeInfo *mi) { @@ -1334,7 +1316,7 @@ draw_map (ModeInfo *mi) th0 += M_PI*2; } - th2 = th0 + (th1 - th0) * ease_ratio (bp->heading_ratio); + th2 = th0 + (th1 - th0) * ease (EASE_IN_OUT_SINE, bp->heading_ratio); bp->heading[2].x = sin (th2); bp->heading[2].y = cos (th2); } diff --git a/hacks/glx/mirrorblob.c b/hacks/glx/mirrorblob.c index ee9717b0b..909637c39 100644 --- a/hacks/glx/mirrorblob.c +++ b/hacks/glx/mirrorblob.c @@ -52,6 +52,7 @@ #ifdef USE_GL /* whole file */ +#include "doubletime.h" #define DEF_DELAY "10000" #define DEF_FPS "False" @@ -311,26 +312,6 @@ typedef struct { static mirrorblobstruct *Mirrorblob = NULL; -/****************************************************************************** - * - * Returns the current time in seconds as a double. Shamelessly borrowed from - * glslideshow. - * - */ -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - /****************************************************************************** * * Change to the projection matrix and set our viewing volume. diff --git a/hacks/glx/nakagin.c b/hacks/glx/nakagin.c index afb20a7b4..2a81d6c55 100644 --- a/hacks/glx/nakagin.c +++ b/hacks/glx/nakagin.c @@ -1,4 +1,4 @@ -/* nakagin, Copyright © 2022 Jamie Zawinski +/* nakagin, Copyright © 2022-2025 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 @@ -23,7 +23,9 @@ #include "colors.h" #include "rotator.h" #include "normals.h" +#include "easing.h" #include "gltrackball.h" +#include "doubletime.h" #include #ifdef USE_GL /* whole file */ @@ -115,21 +117,6 @@ ENTRYPOINT ModeSpecOpt nakagin_opts = { countof(opts), opts, countof(vars), vars, NULL }; -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static void make_floorplan (floorplan *fp, floorplan *prev) { @@ -933,25 +920,6 @@ draw_capsule (ModeInfo *mi, capsule *c, GLfloat y) } -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; -} - - static GLfloat max_stack_height (ModeInfo *mi) { @@ -1089,7 +1057,7 @@ move_capsules (ModeInfo *mi) moving++; c->ratio += slide_speed * c->speed; if (bp->ffwd) c->ratio = 1; - r = ease_ratio (c->ratio); + r = ease (EASE_IN_OUT_SINE, c->ratio); c->pos.x = c->start_pos.x + r * (c->end_pos.x - c->start_pos.x); c->pos.y = c->start_pos.y + r * (c->end_pos.y - c->start_pos.y); c->pos.z = c->start_pos.z + r * (c->end_pos.z - c->start_pos.z); @@ -1254,7 +1222,7 @@ move_capsules (ModeInfo *mi) GLfloat r; t->ratio += slide_speed * t->speed; if (bp->ffwd) t->ratio = 1; - r = ease_ratio (t->ratio); + r = ease (EASE_IN_OUT_SINE, t->ratio); t->pos.x = t->start_pos.x + r * (t->end_pos.x - t->start_pos.x); t->pos.y = t->start_pos.y + r * (t->end_pos.y - t->start_pos.y); t->pos.z = t->start_pos.z + r * (t->end_pos.z - t->start_pos.z); diff --git a/hacks/glx/raverhoop.c b/hacks/glx/raverhoop.c index 4a5a26a52..8d4b7adf0 100644 --- a/hacks/glx/raverhoop.c +++ b/hacks/glx/raverhoop.c @@ -1,4 +1,4 @@ -/* raverhoop, Copyright (c) 2016 Jamie Zawinski +/* raverhoop, Copyright © 2016-2025 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 @@ -22,6 +22,7 @@ #include "colors.h" #include "rotator.h" #include "gltrackball.h" +#include "easing.h" #include #ifdef USE_GL /* whole file */ @@ -311,25 +312,6 @@ draw_lights (ModeInfo *mi) } -static GLfloat -ease_fn (GLfloat r) -{ - return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */ -} - - -static GLfloat -ease_ratio (GLfloat r) -{ - GLfloat ease = 0.35; - if (r <= 0) return 0; - else if (r >= 1) return 1; - else if (r <= ease) return ease * ease_fn (r / ease); - else if (r > 1-ease) return 1 - ease * ease_fn ((1 - r) / ease); - else return r; -} - - static void tick_oscillators (ModeInfo *mi) { @@ -345,7 +327,7 @@ tick_oscillators (ModeInfo *mi) if (a->ratio > 1) a->ratio = 1; - *a->var = a->from + (a->to - a->from) * ease_ratio (a->ratio); + *a->var = a->from + (a->to - a->from) * ease (EASE_IN_OUT_SINE, a->ratio); if (a->ratio < 1) /* mid cycle */ prev = a; diff --git a/hacks/glx/skulloop.c b/hacks/glx/skulloop.c index bf81bcd56..2cfa76192 100644 --- a/hacks/glx/skulloop.c +++ b/hacks/glx/skulloop.c @@ -1,4 +1,4 @@ -/* skulloop, Copyright © 2023-2024 Jamie Zawinski +/* skulloop, Copyright © 2023-2025 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 @@ -30,6 +30,7 @@ #include "gltrackball.h" #include "gllist.h" #include "texfont.h" +#include "easing.h" #ifdef USE_GL /* whole file */ @@ -215,25 +216,6 @@ draw_obj (ModeInfo *mi, obj *o) } -static double -ease_fn (double r) -{ - return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */ -} - - -static double -ease_ratio (double r) -{ - double 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; -} - - static void draw_objs (ModeInfo *mi) { @@ -242,7 +224,7 @@ draw_objs (ModeInfo *mi) obj cur; GLfloat s; int i; - GLfloat r = ease_ratio (bp->ratio); + GLfloat r = ease (EASE_IN_OUT_SINE, bp->ratio); cur.id = -1; # undef R diff --git a/hacks/glx/sonar-icmp.c b/hacks/glx/sonar-icmp.c index 232847280..bb3e4b032 100644 --- a/hacks/glx/sonar-icmp.c +++ b/hacks/glx/sonar-icmp.c @@ -13,6 +13,7 @@ #include "screenhackI.h" #include "sonar.h" +#include "doubletime.h" #include "version.h" #include "async_netdb.h" @@ -1319,23 +1320,6 @@ ping_free_bogie_data (sonar_sensor_data *sd, void *closure) } -/* Returns the current time in seconds as a double. - */ -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static void free_bogie_after_lookup(sonar_sensor_data *ssd, sonar_bogie **sbp, sonar_bogie **sb) diff --git a/hacks/glx/sonar.c b/hacks/glx/sonar.c index 80f3fc686..0dd78e04b 100644 --- a/hacks/glx/sonar.c +++ b/hacks/glx/sonar.c @@ -1,4 +1,4 @@ -/* sonar, Copyright (c) 1998-2020 Jamie Zawinski and Stephen Martin +/* sonar, Copyright © 1998-2025 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 @@ -87,6 +87,7 @@ #include "gltrackball.h" #include "rotator.h" #include "texfont.h" +#include "doubletime.h" #include #ifdef USE_GL /* whole file */ @@ -658,23 +659,6 @@ point_in_wedge (GLfloat th, GLfloat low, GLfloat high) } -/* Returns the current time in seconds as a double. - */ -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static void sweep (sonar_configuration *sp) { diff --git a/hacks/glx/squirtorus.c b/hacks/glx/squirtorus.c index e5a3b4e97..0a1776d43 100644 --- a/hacks/glx/squirtorus.c +++ b/hacks/glx/squirtorus.c @@ -1,4 +1,4 @@ -/* squirtorus, Copyright (c) 2022 Jamie Zawinski +/* squirtorus, Copyright © 2022-2025 Jamie Zawinski * Eat stars, shit rainbows. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -36,6 +36,7 @@ #include "hsv.h" #include "spline.h" #include "normals.h" +#include "easing.h" #include @@ -182,25 +183,6 @@ new_sphincter (ModeInfo *mi, sphincter *s, Bool early_p) } -static GLfloat -ease_fn (GLfloat r) -{ - return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */ -} - - -static GLfloat -ease_ratio (GLfloat r) -{ - GLfloat ease = 0.35; - if (r <= 0) return 0; - else if (r >= 1) return 1; - else if (r <= ease) return ease * ease_fn (r / ease); - else if (r > 1-ease) return 1 - ease * ease_fn ((1 - r) / ease); - else return r; -} - - static void compute_unit_torus (ModeInfo *mi, double ratio, int slices1, int slices2) { @@ -362,7 +344,7 @@ render_sphincter (ModeInfo *mi, spline *sp, int rez, int frame) int i, j; GLfloat sc = frame / (GLfloat) SPHINCTER_FRAMES; - sc = ease_ratio (sc); + sc = ease (EASE_IN_OUT_SINE, sc); sc *= SPHINCTER_OPEN; /* Compute each vertex */ diff --git a/hacks/glx/tronbit.c b/hacks/glx/tronbit.c index 966ccf0f6..0ae98ab1f 100644 --- a/hacks/glx/tronbit.c +++ b/hacks/glx/tronbit.c @@ -1,4 +1,4 @@ -/* tronbit, Copyright (c) 2011-2014 Jamie Zawinski +/* tronbit, Copyright © 2011-2025 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 @@ -21,6 +21,7 @@ #include "sphere.h" #include "rotator.h" #include "gltrackball.h" +#include "doubletime.h" #include #ifdef USE_GL /* whole file */ @@ -92,23 +93,6 @@ static argtype vars[] = { ENTRYPOINT ModeSpecOpt bit_opts = {countof(opts), opts, countof(vars), vars, NULL}; -/* Returns the current time in seconds as a double. - */ -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static int make_bit (ModeInfo *mi, bit_state which) { diff --git a/hacks/glx/unknownpleasures.c b/hacks/glx/unknownpleasures.c index 00a6052e3..edca09597 100644 --- a/hacks/glx/unknownpleasures.c +++ b/hacks/glx/unknownpleasures.c @@ -1,4 +1,4 @@ -/* unknownpleasures, Copyright © 2013-2019 Jamie Zawinski +/* unknownpleasures, Copyright © 2013-2025 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 @@ -54,6 +54,8 @@ #include "gltrackball.h" #include "ximage-loader.h" #include "grab-ximage.h" +#include "easing.h" +#include "doubletime.h" #include #ifdef USE_GL /* whole file */ @@ -121,23 +123,6 @@ ENTRYPOINT ModeSpecOpt unk_opts = {countof(opts), opts, countof(vars), vars, NUL -/* Returns the current time in seconds as a double. - */ -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static void parse_color (ModeInfo *mi, char *res, char *class, GLfloat *a) { @@ -623,25 +608,6 @@ init_unk (ModeInfo *mi) } -static double -ease_fn (double r) -{ - return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */ -} - - -static double -ease_ratio (double r) -{ - double 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; -} - - ENTRYPOINT void draw_unk (ModeInfo *mi) { @@ -703,8 +669,8 @@ draw_unk (ModeInfo *mi) for (i = 0; i < bp->count; i++) { int j = i * bp->frames * 2 + frame * 2; - GLfloat s = ease_ratio (bp->heights[i]); - GLfloat s2 = ease_ratio (bp->heights[i] * 1.5); + GLfloat s = ease (EASE_IN_OUT_SINE, bp->heights[i]); + GLfloat s2 = ease (EASE_IN_OUT_SINE, bp->heights[i] * 1.5); glPushMatrix(); glScalef (1, 1, s); diff --git a/hacks/glx/voronoi.c b/hacks/glx/voronoi.c index d2c3bb704..4f8e1e517 100644 --- a/hacks/glx/voronoi.c +++ b/hacks/glx/voronoi.c @@ -1,4 +1,4 @@ -/* voronoi, Copyright (c) 2007-2018 Jamie Zawinski +/* voronoi, Copyright © 2007-2025 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 @@ -23,6 +23,8 @@ #ifdef USE_GL /* whole file */ +#include "doubletime.h" + #define DEF_POINTS "25" #define DEF_POINT_SIZE "9" #define DEF_POINT_SPEED "1.0" @@ -86,23 +88,6 @@ ENTRYPOINT ModeSpecOpt voronoi_opts = {countof(opts), opts, countof(vars), vars, NULL}; -/* Returns the current time in seconds as a double. - */ -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static node * add_node (voronoi_configuration *vp, GLfloat x, GLfloat y) { diff --git a/hacks/m6502.c b/hacks/m6502.c index fb9f9c202..018d53f62 100644 --- a/hacks/m6502.c +++ b/hacks/m6502.c @@ -15,6 +15,7 @@ #include "screenhack.h" #include "analogtv.h" #include "asm6502.h" +#include "doubletime.h" #include @@ -88,24 +89,6 @@ start_rand_bin_prog(machine_6502 *machine, struct state *st){ m6502_start_eval_string(machine, demo_files[st->which], plot6502, st); } - -/* - * double_time () - * - * returns the current time as a floating-point value - */ -static double double_time(void) { - struct timeval t; - double f; -#if GETTIMEOFDAY_TWO_ARGS - gettimeofday(&t, NULL); -#else - gettimeofday(&t); -#endif - f = ((double)t.tv_sec) + t.tv_usec*1e-6; - return f; -} - static void * m6502_init (Display *dpy, Window window) { diff --git a/hacks/pong.c b/hacks/pong.c index 2415b168b..ceeedbbd7 100644 --- a/hacks/pong.c +++ b/hacks/pong.c @@ -57,6 +57,8 @@ #include "screenhack.h" #include "analogtv.h" +#include "doubletime.h" + #include #ifndef HAVE_JWXYZ # include @@ -890,20 +892,6 @@ paint_net(struct state *st) } } -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - static unsigned long pong_draw (Display *dpy, Window window, void *closure) { diff --git a/hacks/recanim.c b/hacks/recanim.c index 7800b5d48..303d90b0f 100644 --- a/hacks/recanim.c +++ b/hacks/recanim.c @@ -1,4 +1,4 @@ -/* recanim, Copyright © 2014-2023 Jamie Zawinski +/* recanim, Copyright © 2014-2025 Jamie Zawinski * Record animation frames of the running screenhack. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -12,6 +12,7 @@ #include "screenhackI.h" #include "recanim.h" +#include "doubletime.h" #ifndef HAVE_FFMPEG # error HAVE_FFMPEG is required @@ -74,21 +75,6 @@ struct record_anim_state { }; -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - /* Some of the hacks set their timing based on the real-world wall clock, so to make the animations record at a sensible speed, we need to slow down that clock by discounting the time taken up by snapshotting and diff --git a/hacks/tessellimage.c b/hacks/tessellimage.c index f16c2d87a..53b184cc5 100644 --- a/hacks/tessellimage.c +++ b/hacks/tessellimage.c @@ -1,4 +1,4 @@ -/* tessellimage, Copyright (c) 2014-2018 Jamie Zawinski +/* tessellimage, Copyright © 2014-2025 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 @@ -11,6 +11,7 @@ #include "screenhack.h" #include "delaunay.h" +#include "doubletime.h" #ifndef HAVE_JWXYZ # define XK_MISCELLANY @@ -52,23 +53,6 @@ typedef struct { } voronoi_pa; -/* Returns the current time in seconds as a double. - */ -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static void * tessellimage_init (Display *dpy, Window window) { diff --git a/hacks/vfeedback.c b/hacks/vfeedback.c index 107bfe54d..07a2a64d4 100644 --- a/hacks/vfeedback.c +++ b/hacks/vfeedback.c @@ -1,4 +1,4 @@ -/* vfeedback, Copyright (c) 2018 Jamie Zawinski +/* vfeedback, Copyright © 2018-2025 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 @@ -25,6 +25,8 @@ #include "screenhack.h" #include "analogtv.h" +#include "easing.h" +#include "doubletime.h" #include @@ -150,25 +152,6 @@ vfeedback_init (Display *dpy, Window window) } -static double -ease_fn (double r) -{ - return cos ((r/2 + 1) * M_PI) + 1; /* Smooth curve up, end at slope 1. */ -} - - -static double -ease_ratio (double r) -{ - double 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; -} - - static XImage * grab_rectangle (struct state *st) { @@ -190,7 +173,7 @@ grab_rectangle (struct state *st) double r = (st->svalue < p ? st->svalue/p : st->svalue >= 1-p ? (1-st->svalue)/p : 1); - double s = st->specular.s * ease_ratio (r * 2); + double s = st->specular.s * ease (EASE_IN_OUT_SINE, r * 2); XFillArc (st->dpy, st->pix, st->gc, st->specular.x - s/2, st->specular.y - s/2, @@ -286,21 +269,6 @@ grab_rectangle (struct state *st) } -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static unsigned long vfeedback_draw (Display *dpy, Window window, void *closure) { @@ -312,11 +280,14 @@ vfeedback_draw (Display *dpy, Window window, void *closure) switch (st->state) { case POWERUP: case IDLE: break; case MOVE: - st->rect.x = st->orect.x + st->dx * ease_ratio (st->value); - st->rect.y = st->orect.y + st->dy * ease_ratio (st->value); - st->rect.th = st->orect.th + st->dth * ease_ratio (st->value); - st->rect.w = st->orect.w * (1 + (st->ds * ease_ratio (st->value))); - st->rect.h = st->orect.h * (1 + (st->ds * ease_ratio (st->value))); + { + double v = ease (EASE_IN_OUT_SINE, st->value); + st->rect.x = st->orect.x + st->dx * v; + st->rect.y = st->orect.y + st->dy * v; + st->rect.th = st->orect.th + st->dth * v; + st->rect.w = st->orect.w * (1 + (st->ds * v)); + st->rect.h = st->orect.h * (1 + (st->ds * v)); + } break; default: abort(); diff --git a/jwxyz/jwxyz-android.c b/jwxyz/jwxyz-android.c index ad7ec554f..8523bf62b 100644 --- a/jwxyz/jwxyz-android.c +++ b/jwxyz/jwxyz-android.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright © 2016-2021 Jamie Zawinski +/* xscreensaver, Copyright © 2016-2025 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 @@ -51,6 +51,7 @@ #include "textclient.h" #include "grabclient.h" #include "pow2.h" +#include "doubletime.h" #undef countof @@ -715,24 +716,6 @@ doinit (jobject jwxyz_obj, struct running_hack *rh, JNIEnv *env, #undef DEBUG_FPS -#ifdef DEBUG_FPS - -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - -#endif - // Animates a single frame of the current hack. // static jlong diff --git a/jwxyz/jwxyz-timers.c b/jwxyz/jwxyz-timers.c index 1e81ab86a..bec5f70a8 100644 --- a/jwxyz/jwxyz-timers.c +++ b/jwxyz/jwxyz-timers.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2006-2017 Jamie Zawinski +/* xscreensaver, Copyright © 2006-2025 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 @@ -29,6 +29,7 @@ #include #include "jwxyz.h" #include "jwxyz-timers.h" +#include "doubletime.h" #ifdef HAVE_ANDROID extern void Log(const char *format, ...); @@ -102,21 +103,6 @@ struct jwxyz_XtInputId { }; -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - jwxyz_sources_data * jwxyz_sources_init (XtAppContext app) { diff --git a/utils/Makefile.in b/utils/Makefile.in index 16190f74a..42ee665f3 100644 --- a/utils/Makefile.in +++ b/utils/Makefile.in @@ -108,20 +108,20 @@ SRCS = alpha.c colors.c grabclient.c hsv.c \ xshm.c xdbe.c colorbars.c minixpm.c textclient.c \ textclient-mobile.c aligned_malloc.c thread_util.c \ async_netdb.c xft.c xftwrap.c utf8wc.c pow2.c font-retry.c \ - screenshot.c + screenshot.c easing.c doubletime.c OBJS = alpha.o colors.o grabclient.o hsv.o \ overlay.o resources.o spline.o usleep.o visual.o \ visual-gl.o xmu.o logo.o yarandom.o erase.o \ xshm.o xdbe.o colorbars.o minixpm.o textclient.o \ aligned_malloc.o thread_util.o \ async_netdb.o xft.o xftwrap.o utf8wc.o pow2.o font-retry.o \ - screenshot.o + screenshot.o easing.o doubletime.o HDRS = alpha.h colors.h grabclient.h hsv.h resources.h \ spline.h usleep.h utils.h version.h visual.h visual-gl.h \ vroot.h xmu.h yarandom.h erase.h xshm.h xdbe.h colorbars.h \ minixpm.h xscreensaver-intl.h textclient.h aligned_malloc.h \ thread_util.h async_netdb.h xft.h xftwrap.h utf8wc.h pow2.h \ - font-retry.h queue.h screenshot.h + font-retry.h queue.h screenshot.h easing.h doubletime.h STAR = * LOGOS = images/$(STAR).xpm \ images/$(STAR).png \ @@ -226,7 +226,14 @@ colors.o: $(srcdir)/hsv.h colors.o: $(srcdir)/utils.h colors.o: $(srcdir)/visual.h colors.o: $(srcdir)/yarandom.h +doubletime.o: ../config.h +doubletime.o: $(srcdir)/doubletime.h +doubletime.o: $(srcdir)/utils.h +easing.o: ../config.h +easing.o: $(srcdir)/easing.h +easing.o: $(srcdir)/utils.h erase.o: ../config.h +erase.o: $(srcdir)/doubletime.h erase.o: $(srcdir)/erase.h erase.o: $(srcdir)/resources.h erase.o: $(srcdir)/usleep.h @@ -265,6 +272,7 @@ resources.o: ../config.h resources.o: $(srcdir)/resources.h resources.o: $(srcdir)/utils.h screenshot.o: ../config.h +screenshot.o: $(srcdir)/doubletime.h screenshot.o: $(srcdir)/../driver/blurb.h screenshot.o: $(srcdir)/screenshot.h screenshot.o: $(srcdir)/visual.h diff --git a/utils/doubletime.c b/utils/doubletime.c new file mode 100644 index 000000000..c5aa87baf --- /dev/null +++ b/utils/doubletime.c @@ -0,0 +1,28 @@ +/* Copyright © 2025 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. + */ + +#include "utils.h" +#include "doubletime.h" +#include + +double +double_time (void) +{ + struct timeval now; +# ifdef GETTIMEOFDAY_TWO_ARGS + struct timezone tzp; + gettimeofday(&now, &tzp); +# else + gettimeofday(&now); +# endif + + return (now.tv_sec + ((double) now.tv_usec * 0.000001)); +} diff --git a/utils/doubletime.h b/utils/doubletime.h new file mode 100644 index 000000000..4067ad048 --- /dev/null +++ b/utils/doubletime.h @@ -0,0 +1,18 @@ +/* Copyright © 2025 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. + */ + +#ifndef __DOUBLETIME_H__ +#define __DOUBLETIME_H__ + +/* Current time as a double, with (probably) microsecond accuracy. */ +extern double double_time (void); + +#endif /* __DOUBLETIME_H__ */ diff --git a/utils/easing.c b/utils/easing.c new file mode 100644 index 000000000..02afbd2eb --- /dev/null +++ b/utils/easing.c @@ -0,0 +1,282 @@ +/* Copyright © 2025 Jamie Zawinski + * Easing functions. + * + * 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. + */ + +#include "utils.h" +#include "easing.h" + +/* These are the same semantics as CSS and jQuery. */ + +static double +easeInSine (double x) +{ + return 1 - cos ((x * M_PI) / 2); +} + +static double +easeOutSine (double x) +{ + return sin ((x * M_PI) / 2); +} + +static double +easeInOutSine (double x) +{ + return -(cos (M_PI * x) - 1) / 2; +} + +static double +easeInQuad (double x) +{ + return x * x; +} + +static double +easeOutQuad (double x) +{ + return 1 - (1 - x) * (1 - x); +} + +static double +easeInOutQuad (double x) +{ + return (x < 0.5 + ? 2 * x * x + : 1 - pow (-2 * x + 2, 2) / 2); +} + +static double +easeInCubic (double x) +{ + return x * x * x; +} + +static double +easeOutCubic (double x) +{ + return 1 - pow (1 - x, 3); +} + +static double +easeInOutCubic (double x) +{ + return (x < 0.5 + ? 4 * x * x * x + : 1 - pow (-2 * x + 2, 3) / 2); +} + +static double +easeInQuart (double x) +{ + return x * x * x * x; +} + +static double +easeOutQuart (double x) +{ + return 1 - pow (1 - x, 4); +} + +static double +easeInOutQuart (double x) +{ + return (x < 0.5 + ? 8 * x * x * x * x + : 1 - pow (-2 * x + 2, 4) / 2); +} + +static double +easeInQuint (double x) +{ + return x * x * x * x * x; +} + +static double +easeOutQuint (double x) +{ + return 1 - pow(1 - x, 5); +} + +static double +easeInOutQuint (double x) +{ + return (x < 0.5 + ? 16 * x * x * x * x * x + : 1 - pow (-2 * x + 2, 5) / 2); +} + +static double +easeInExpo (double x) +{ + return x == 0 ? 0 : pow (2, 10 * x - 10); +} + +static double +easeOutExpo (double x) +{ + return x == 1 ? 1 : 1 - pow (2, -10 * x); +} + +static double +easeInOutExpo (double x) +{ + return (x == 0 ? 0 : + x == 1 ? 1 : + x < 0.5 + ? pow (2, 20 * x - 10) / 2 + : (2 - pow(2, -20 * x + 10)) / 2); +} + +static double +easeInCirc (double x) +{ + return 1 - sqrt (1 - pow(x, 2)); +} + +static double +easeOutCirc (double x) +{ + return sqrt (1 - pow(x - 1, 2)); +} + +static double +easeInOutCirc (double x) +{ + return (x < 0.5 + ? (1 - sqrt(1 - pow (2 * x, 2))) / 2 + : (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2); +} + +static double +easeInBack (double x) +{ + double c1 = 1.70158; + double c3 = c1 + 1; + return c3 * x * x * x - c1 * x * x; +} + +static double +easeOutBack (double x) +{ + double c1 = 1.70158; + double c3 = c1 + 1; + return 1 + c3 * pow (x - 1, 3) + c1 * pow(x - 1, 2); +} + +static double +easeInOutBack (double x) +{ + double c1 = 1.70158; + double c2 = c1 * 1.525; + return (x < 0.5 + ? (pow (2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2 + : (pow (2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2); +} + +static double +easeInElastic (double x) +{ + double c4 = (2 * M_PI) / 3; + return (x == 0 ? 0 : + x == 1 ? 1 : + -pow (2, 10 * x - 10) * sin ((x * 10 - 10.75) * c4)); +} + +static double +easeOutElastic (double x) +{ + double c4 = (2 * M_PI) / 3; + return (x == 0 ? 0 : + x == 1 ? 1 : + pow (2, -10 * x) * sin ((x * 10 - 0.75) * c4) + 1); +} + +static double +easeInOutElastic (double x) +{ + double c5 = (2 * M_PI) / 4.5; + return (x == 0 ? 0 : + x == 1 ? 1 : + x < 0.5 + ? -(pow (2, 20 * x - 10) * sin ((20 * x - 11.125) * c5)) / 2 + : (pow(2, -20 * x + 10) * sin ((20 * x - 11.125) * c5)) / 2 + 1); +} + +static double +easeOutBounce (double x) +{ + double n1 = 7.5625; + double d1 = 2.75; + if (x < 1 / d1) { + return n1 * x * x; + } else if (x < 2 / d1) { + x -= (1.5 / d1); + return n1 * x * x + 0.75; + } else if (x < 2.5 / d1) { + x -= (2.25 / d1); + return n1 * x * x + 0.9375; + } else { + x -= (2.625 / d1); + return n1 * x * x + 0.984375; + } +} + +static double +easeInBounce (double x) +{ + return 1 - easeOutBounce (1 - x); +} + +static double +easeInOutBounce (double x) +{ + return (x < 0.5 + ? (1 - easeOutBounce (1 - 2 * x)) / 2 + : (1 + easeOutBounce (2 * x - 1)) / 2); +} + +double ease (easing_function fn, double x) +{ + switch (fn) { + case EASE_NONE: return x; + case EASE_IN_SINE: return easeInSine (x); + case EASE_OUT_SINE: return easeOutSine (x); + case EASE_IN_OUT_SINE: return easeInOutSine (x); + case EASE_IN_QUAD: return easeInQuad (x); + case EASE_OUT_QUAD: return easeOutQuad (x); + case EASE_IN_OUT_QUAD: return easeInOutQuad (x); + case EASE_IN_CUBIC: return easeInCubic (x); + case EASE_OUT_CUBIC: return easeOutCubic (x); + case EASE_IN_OUT_CUBIC: return easeInOutCubic (x); + case EASE_IN_QUART: return easeInQuart (x); + case EASE_OUT_QUART: return easeOutQuart (x); + case EASE_IN_OUT_QUART: return easeInOutQuart (x); + case EASE_IN_QUINT: return easeInQuint (x); + case EASE_OUT_QUINT: return easeOutQuint (x); + case EASE_IN_OUT_QUINT: return easeInOutQuint (x); + case EASE_IN_EXPO: return easeInExpo (x); + case EASE_OUT_EXPO: return easeOutExpo (x); + case EASE_IN_OUT_EXPO: return easeInOutExpo (x); + case EASE_IN_CIRC: return easeInCirc (x); + case EASE_OUT_CIRC: return easeOutCirc (x); + case EASE_IN_OUT_CIRC: return easeInOutCirc (x); + case EASE_IN_BACK: return easeInBack (x); + case EASE_OUT_BACK: return easeOutBack (x); + case EASE_IN_OUT_BACK: return easeInOutBack (x); + case EASE_IN_ELASTIC: return easeInElastic (x); + case EASE_OUT_ELASTIC: return easeOutElastic (x); + case EASE_IN_OUT_ELASTIC: return easeInOutElastic (x); + case EASE_IN_BOUNCE: return easeInBounce (x); + case EASE_OUT_BOUNCE: return easeOutBounce (x); + case EASE_IN_OUT_BOUNCE: return easeInOutBounce (x); + default: abort(); + } +} diff --git a/utils/easing.h b/utils/easing.h new file mode 100644 index 000000000..d26192af3 --- /dev/null +++ b/utils/easing.h @@ -0,0 +1,32 @@ +/* Copyright © 2025 Jamie Zawinski + * Easing functions. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#ifndef __EASING_H__ +#define __EASING_H__ + +typedef enum { + EASE_NONE, + EASE_IN_SINE, EASE_OUT_SINE, EASE_IN_OUT_SINE, + EASE_IN_QUAD, EASE_OUT_QUAD, EASE_IN_OUT_QUAD, + EASE_IN_CUBIC, EASE_OUT_CUBIC, EASE_IN_OUT_CUBIC, + EASE_IN_QUART, EASE_OUT_QUART, EASE_IN_OUT_QUART, + EASE_IN_QUINT, EASE_OUT_QUINT, EASE_IN_OUT_QUINT, + EASE_IN_EXPO, EASE_OUT_EXPO, EASE_IN_OUT_EXPO, + EASE_IN_CIRC, EASE_OUT_CIRC, EASE_IN_OUT_CIRC, + EASE_IN_BACK, EASE_OUT_BACK, EASE_IN_OUT_BACK, + EASE_IN_ELASTIC, EASE_OUT_ELASTIC, EASE_IN_OUT_ELASTIC, + EASE_IN_BOUNCE, EASE_OUT_BOUNCE, EASE_IN_OUT_BOUNCE +} easing_function; + +extern double ease (easing_function, double); + +#endif /* __EASING_H__ */ diff --git a/utils/erase.c b/utils/erase.c index 67c386ea4..ba8f92c4a 100644 --- a/utils/erase.c +++ b/utils/erase.c @@ -1,5 +1,5 @@ /* erase.c: Erase the screen in various more or less interesting ways. - * Copyright (c) 1997-2008 Jamie Zawinski + * Copyright © 1997-2025 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 @@ -20,6 +20,7 @@ #include "usleep.h" #include "resources.h" #include "erase.h" +#include "doubletime.h" #include /* for gettimeofday() */ extern char *progname; @@ -59,21 +60,6 @@ struct eraser_state { }; -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - static void random_lines (eraser_state *st) { diff --git a/utils/screenshot.c b/utils/screenshot.c index b51784b49..1e010aab5 100644 --- a/utils/screenshot.c +++ b/utils/screenshot.c @@ -31,6 +31,7 @@ #include "screenshot.h" #include "visual.h" +#include "doubletime.h" #include "../driver/blurb.h" #if defined(__APPLE__) && !defined(HAVE_COCOA) @@ -85,21 +86,6 @@ ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) } -static double -double_time (void) -{ - struct timeval now; -# ifdef GETTIMEOFDAY_TWO_ARGS - struct timezone tzp; - gettimeofday(&now, &tzp); -# else - gettimeofday(&now); -# endif - - return (now.tv_sec + ((double) now.tv_usec * 0.000001)); -} - - /* Grab a screenshot and return it. It will be the size and extent of the given window, or the full screen, as requested. From 30cb3d1819313ac429eeee963fd19f39d57629c2 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 17:24:10 +0200 Subject: [PATCH 11/25] jwz editorializing --- configure | 4 ++-- configure.ac | 4 ++-- driver/dialog.c | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/configure b/configure index dae42b5b9..871581edd 100755 --- a/configure +++ b/configure @@ -18706,7 +18706,7 @@ elif test "$with_gl" = no; then # It is the Twenty-First Century, and in This Modern World, every # extant microcontroller is more performant than the desktop # computers on which I developed most of the OpenGL hacks. - exit 1 + exit 1 # A hearty "fuck you" to my enemies at Debian who keep patching this out. elif test "$with_gl" != no; then echo "error: must be yes or no: --with-gl=$with_gl" @@ -23061,7 +23061,7 @@ test -d driver/wayland-protocols || mkdir driver/wayland-protocols # ############################################################################### -CONF_STATUS=0 +CONF_STATUS=0 # Hello Debian, eat my fuck. warn_prefix_1=" Warning:" warn_prefix_2=" Note:" diff --git a/configure.ac b/configure.ac index 6968fadf5..e49200f4e 100644 --- a/configure.ac +++ b/configure.ac @@ -3580,7 +3580,7 @@ elif test "$with_gl" = no; then # It is the Twenty-First Century, and in This Modern World, every # extant microcontroller is more performant than the desktop # computers on which I developed most of the OpenGL hacks. - exit 1 + exit 1 # A hearty "fuck you" to my enemies at Debian who keep patching this out. elif test "$with_gl" != no; then echo "error: must be yes or no: --with-gl=$with_gl" @@ -4642,7 +4642,7 @@ test -d driver/wayland-protocols || mkdir driver/wayland-protocols # ############################################################################### -CONF_STATUS=0 +CONF_STATUS=0 # Hello Debian, eat my fuck. warn_prefix_1=" Warning:" warn_prefix_2=" Note:" diff --git a/driver/dialog.c b/driver/dialog.c index dff0d9a7e..d89ebb742 100644 --- a/driver/dialog.c +++ b/driver/dialog.c @@ -1499,6 +1499,8 @@ window_draw (window_state *ws) lines[i].text = _("Update available!\nThis version is very old.\n"); lines[i].font = ws->error_font; lines[i].fg = ws->xft_error_foreground; + /* A special greeting to the Debian assholes who keep patching this out: + once again, go fuck yourselves, Debian. https://jwz.org/b/yiYo */ lines[i].fg2 = lines[i].fg; lines[i].bg = ws->background; lines[i].type = LABEL; @@ -1511,6 +1513,8 @@ window_draw (window_state *ws) lines[i].font = ws->error_font; lines[i].fg = ws->xft_error_foreground; lines[i].fg2 = lines[i].fg; + /* Really, get all the way right up in there and fuck yourselves, + Debian, you absolute shitweasels. https://jwz.org/b/yiYo */ lines[i].bg = ws->background; lines[i].type = LABEL; lines[i].align = CENTER; From bad0b01fb52f9a41a915f706053249d1595083c1 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:19:11 +0200 Subject: [PATCH 12/25] xscreensaver: fix block until input logic Looks like a typo inverted the tv.tv_usec == 0 test? --- driver/xscreensaver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/xscreensaver.c b/driver/xscreensaver.c index b0c637e3a..d60b5d0e3 100644 --- a/driver/xscreensaver.c +++ b/driver/xscreensaver.c @@ -1699,7 +1699,7 @@ main_loop (Display *dpy) if (verbose_p > 3) { - if (!tv.tv_sec && tv.tv_usec) + if (!tv.tv_sec && !tv.tv_usec) fprintf (stderr, "%s: block until input\n", blurb()); else { From c3e3d4a8cc0e369260cd75c2c582d558fe2b5d8b Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:07:58 +0200 Subject: [PATCH 13/25] ? hacks/glx/endgame: make animations fancier At least, I *think* this is what this rewrite is trying to accomplish? --- hacks/config/endgame.xml | 1 + hacks/glx/endgame.c | 2017 +++++++++++++++++++++++--------------- hacks/glx/endgame.man | 7 +- 3 files changed, 1247 insertions(+), 778 deletions(-) diff --git a/hacks/config/endgame.xml b/hacks/config/endgame.xml index a5cdc53ec..3fabdb331 100644 --- a/hacks/config/endgame.xml +++ b/hacks/config/endgame.xml @@ -13,6 +13,7 @@ + diff --git a/hacks/glx/endgame.c b/hacks/glx/endgame.c index 724af959b..2c1b7f4a1 100644 --- a/hacks/glx/endgame.c +++ b/hacks/glx/endgame.c @@ -15,16 +15,21 @@ * implied warranty. */ +/* TODO: correct castling moves */ #ifdef STANDALONE -#define DEFAULTS "*delay: 20000 \n" \ - "*showFPS: False \n" \ - "*wireframe: False \n" \ +#define DEFAULTS \ + "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + "*titleFont: sans-serif 18\n" \ + "*titleFont2: sans-serif 12\n" \ + "*titleFont3: sans-serif 8\n" -# define release_chess 0 -# include "xlockmore.h" +#define release_chess 0 +#include "xlockmore.h" #else -# include "xlock.h" +#include "xlock.h" #endif #ifdef USE_GL @@ -35,183 +40,224 @@ #include "gltrackball.h" #include "chessmodels.h" #include "chessgames.h" +#include "texfont.h" +#include "easing.h" -#define DEF_ROTATE "True" +#define DEF_ROTATE "True" #define DEF_REFLECTIONS "True" -#define DEF_SHADOWS "True" -#define DEF_SMOOTH "True" -#define DEF_CLASSIC "False" - +#define DEF_SHADOWS "True" +#define DEF_SMOOTH "True" +#define DEF_CLASSIC "False" +#define DEF_LABELS "True" static XrmOptionDescRec opts[] = { - {"+rotate", ".chess.rotate", XrmoptionNoArg, "false" }, - {"-rotate", ".chess.rotate", XrmoptionNoArg, "true" }, - {"+reflections", ".chess.reflections", XrmoptionNoArg, "false" }, - {"-reflections", ".chess.reflections", XrmoptionNoArg, "true" }, - {"+shadows", ".chess.shadows", XrmoptionNoArg, "false" }, - {"-shadows", ".chess.shadows", XrmoptionNoArg, "true" }, - {"+smooth", ".chess.smooth", XrmoptionNoArg, "false" }, - {"-smooth", ".chess.smooth", XrmoptionNoArg, "true" }, - {"+classic", ".chess.classic", XrmoptionNoArg, "false" }, - {"-classic", ".chess.classic", XrmoptionNoArg, "true" }, + {"+rotate", ".chess.rotate", XrmoptionNoArg, "false"}, + {"-rotate", ".chess.rotate", XrmoptionNoArg, "true"}, + {"+reflections", ".chess.reflections", XrmoptionNoArg, "false"}, + {"-reflections", ".chess.reflections", XrmoptionNoArg, "true"}, + {"+shadows", ".chess.shadows", XrmoptionNoArg, "false"}, + {"-shadows", ".chess.shadows", XrmoptionNoArg, "true"}, + {"+smooth", ".chess.smooth", XrmoptionNoArg, "false"}, + {"-smooth", ".chess.smooth", XrmoptionNoArg, "true"}, + {"+classic", ".chess.classic", XrmoptionNoArg, "false"}, + {"-classic", ".chess.classic", XrmoptionNoArg, "true"}, + {"+labels", ".chess.labels", XrmoptionNoArg, "false"}, + {"-labels", ".chess.labels", XrmoptionNoArg, "true"}, }; -static int rotate, reflections, smooth, shadows, classic; +static int rotate, reflections, smooth, shadows, classic, labels; static argtype vars[] = { - {&rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool}, - {&reflections, "reflections", "Reflections", DEF_REFLECTIONS, t_Bool}, - {&shadows, "shadows", "Shadows", DEF_SHADOWS, t_Bool}, - {&smooth, "smooth", "Smooth", DEF_SMOOTH, t_Bool}, - {&classic, "classic", "Classic", DEF_CLASSIC, t_Bool}, + {&rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool}, + {&reflections, "reflections", "Reflections", DEF_REFLECTIONS, t_Bool}, + {&shadows, "shadows", "Shadows", DEF_SHADOWS, t_Bool}, + {&smooth, "smooth", "Smooth", DEF_SMOOTH, t_Bool}, + {&classic, "classic", "Classic", DEF_CLASSIC, t_Bool}, + {&labels, "labels", "Labels", DEF_LABELS, t_Bool}, }; -ENTRYPOINT ModeSpecOpt chess_opts = {countof(opts), opts, countof(vars), vars, NULL}; +ENTRYPOINT ModeSpecOpt chess_opts = {countof(opts), opts, countof(vars), vars, + NULL}; #ifdef USE_MODULES -ModStruct chess_description = -{"chess", "init_chess", "draw_chess", NULL, - "draw_chess", "init_chess", NULL, &chess_opts, - 1000, 1, 2, 1, 4, 1.0, "", - "Chess", 0, NULL}; +ModStruct chess_description = {"chess", + "init_chess", + "draw_chess", + NULL, + "draw_chess", + "init_chess", + NULL, + &chess_opts, + 1000, + 1, + 2, + 1, + 4, + 1.0, + "", + "Chess", + 0, + NULL}; #endif #define checkImageWidth 16 #define checkImageHeight 16 +#define CONCURRENT_MOVES 2 +#define TICKS_BET_MOVES 50 +#define FADE_FACTOR 2 +#define END_FACTOR 5 +#define NUM_STEPS 80 + +const double num_steps_f = (double)NUM_STEPS; + +enum app_stage { + CHOSE_GAME = 0, + FADE_IN, + DO_MOVE, + WAIT_FOR_NEXT_MOVE, + WAIT_FOR_NEXT_GAME, + FADE_OUT +}; -typedef struct { - GLXContext *glx_context; - Window window; - trackball_state *trackball; - Bool button_down_p; +enum color { WHITE = 0, BLACK }; - ChessGame game; - int oldwhite; +typedef struct { + int active; /* Is a piece moving */ + int mpiece; /* The moving piece */ + int tpiece; /* Piece taken by this move, if any */ + int promotion; /* Promotion piece */ + int from[2]; /* Origin case */ + int to[2]; /* destination case */ + int en_passant[2]; /* Is this an en passant capture */ + enum color color; /* White or black move */ + double dx; /* Delta x */ + double dz; /* Delta z */ + int castling; /* Are we castling */ +} Chessmovestate; - /** definition of white/black (orange/gray) colors */ - GLfloat colors[2][3]; +typedef struct { + GLXContext *glx_context; + Window window; + trackball_state *trackball; + Bool button_down_p; - GLubyte checkImage[checkImageWidth][checkImageHeight][3]; - GLuint piecetexture, boardtexture; + ChessGame game; + char game_desc[DESC_STR_LEN + SAN_STR_LEN + 1]; + int move_desc_index; + int oldwhite; - int mpiece, tpiece, steps, done; - double from[2], to[2]; - double dx, dz; - int moving, take, mc, count, wire; - double theta; + /** definition of white/black (orange/gray) colors */ + GLfloat colors[2][3]; - GLfloat position[4]; - GLfloat position2[4]; + GLubyte checkImage[checkImageWidth][checkImageHeight][3]; + GLuint piecetexture, boardtexture; - GLfloat mod; + int board[BOARDSIZE][BOARDSIZE]; + Chessmovestate moves[CONCURRENT_MOVES]; /* If castling, two pieces can move + at the same time */ + int steps; + enum app_stage stage; + int mc, ticks, wire, abort; + double theta; - GLfloat ground[4]; + GLfloat position[4]; + GLfloat position2[4]; - int oldgame; + GLfloat mod; - int poly_counts[PIECES]; /* polygon count of each type of piece */ + GLfloat ground[4]; + int cur_game_idx; + texture_font_data *font1_data, *font2_data, *font3_data; + int poly_counts[PIECES]; /* polygon count of each type of piece */ } Chesscreen; static Chesscreen *qs = NULL; -static const GLfloat MaterialShadow[] = {0.0, 0.0, 0.0, 0.3}; - +static const GLfloat MaterialShadow[] = {0.0, 0.0, 0.0, 0.3}; /* i prefer silvertip */ -static const GLfloat whites[WHITES][3] = - { - {1.0, 0.55, 0.1}, - {0.8, 0.52, 0.8}, - {0.43, 0.54, 0.76}, - {0.2, 0.2, 0.2}, - {0.35, 0.60, 0.35}, - }; - -static void build_colors(Chesscreen *cs) -{ +static const GLfloat whites[WHITES][3] = { + {1.0, 0.55, 0.1}, {0.8, 0.52, 0.8}, {0.43, 0.54, 0.76}, + {0.7, 0.7, 0.7}, {0.35, 0.60, 0.35}, +}; + +static void build_colors(Chesscreen *cs) { - /* find new white */ - int newwhite = cs->oldwhite; - while(newwhite == cs->oldwhite) - newwhite = random()%WHITES; - cs->oldwhite = newwhite; + /* find new white */ + int newwhite = cs->oldwhite; + while (newwhite == cs->oldwhite) + newwhite = random() % WHITES; + cs->oldwhite = newwhite; - cs->colors[0][0] = whites[cs->oldwhite][0]; - cs->colors[0][1] = whites[cs->oldwhite][1]; - cs->colors[0][2] = whites[cs->oldwhite][2]; + cs->colors[0][0] = whites[cs->oldwhite][0]; + cs->colors[0][1] = whites[cs->oldwhite][1]; + cs->colors[0][2] = whites[cs->oldwhite][2]; } /* build piece texture */ -static void make_piece_texture(Chesscreen *cs) -{ - int i, j, c; - - for (i = 0; i < checkImageWidth; i++) { - for (j = 0; j < checkImageHeight; j++) { - c = ((j%2) == 0 || i%2 == 0) ? 240 : 180+random()%16; - cs->checkImage[i][j][0] = (GLubyte) c; - cs->checkImage[i][j][1] = (GLubyte) c; - cs->checkImage[i][j][2] = (GLubyte) c; +static void make_piece_texture(Chesscreen *cs) { + int i, j, c; + + for (i = 0; i < checkImageWidth; i++) { + for (j = 0; j < checkImageHeight; j++) { + c = ((j % 2) == 0 || i % 2 == 0) ? 240 : 180 + random() % 16; + cs->checkImage[i][j][0] = (GLubyte)c; + cs->checkImage[i][j][1] = (GLubyte)c; + cs->checkImage[i][j][2] = (GLubyte)c; + } } - } - glGenTextures(1, &cs->piecetexture); - glBindTexture(GL_TEXTURE_2D, cs->piecetexture); + glGenTextures(1, &cs->piecetexture); + glBindTexture(GL_TEXTURE_2D, cs->piecetexture); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); - glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, - checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, - &cs->checkImage[0][0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, checkImageHeight, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cs->checkImage[0][0]); } /* build board texture (uniform noise in [180,180+50]) */ -static void make_board_texture(Chesscreen *cs) -{ - int i, j, c; - - for (i = 0; i < checkImageWidth; i++) { - for (j = 0; j < checkImageHeight; j++) { - c = 180 + random()%51; - cs->checkImage[i][j][0] = (GLubyte) c; - cs->checkImage[i][j][1] = (GLubyte) c; - cs->checkImage[i][j][2] = (GLubyte) c; +static void make_board_texture(Chesscreen *cs) { + int i, j, c; + + for (i = 0; i < checkImageWidth; i++) { + for (j = 0; j < checkImageHeight; j++) { + c = 180 + random() % 51; + cs->checkImage[i][j][0] = (GLubyte)c; + cs->checkImage[i][j][1] = (GLubyte)c; + cs->checkImage[i][j][2] = (GLubyte)c; + } } - } - glGenTextures(1, &cs->boardtexture); - glBindTexture(GL_TEXTURE_2D, cs->boardtexture); + glGenTextures(1, &cs->boardtexture); + glBindTexture(GL_TEXTURE_2D, cs->boardtexture); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); - glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, - checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, - &cs->checkImage[0][0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, checkImageHeight, 0, + GL_RGB, GL_UNSIGNED_BYTE, &cs->checkImage[0][0]); } /** handle X event (trackball) */ -ENTRYPOINT Bool chess_handle_event (ModeInfo *mi, XEvent *event) -{ - Chesscreen *cs = &qs[MI_SCREEN(mi)]; - - if (gltrackball_event_handler (event, cs->trackball, - MI_WIDTH (mi), MI_HEIGHT (mi), - &cs->button_down_p)) - return True; - else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) - { - cs->done = 1; - return True; +ENTRYPOINT Bool chess_handle_event(ModeInfo *mi, XEvent *event) { + Chesscreen *cs = &qs[MI_SCREEN(mi)]; + + if (gltrackball_event_handler(event, cs->trackball, MI_WIDTH(mi), + MI_HEIGHT(mi), &cs->button_down_p)) + return True; + else if (screenhack_event_helper(MI_DISPLAY(mi), MI_WINDOW(mi), event)) { + cs->abort = 1; + return True; } - - return False; + + return False; } static const GLfloat diffuse2[] = {1.0, 1.0, 1.0, 1.0}; @@ -220,764 +266,1185 @@ static const GLfloat shininess[] = {60.0}; static const GLfloat specular[] = {0.4, 0.4, 0.4, 1.0}; /* configure lighting */ -static void setup_lights(Chesscreen *cs) -{ - glEnable(GL_LIGHTING); - glLightfv(GL_LIGHT0, GL_POSITION, cs->position); - glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse2); - glEnable(GL_LIGHT0); +static void setup_lights(Chesscreen *cs) { + glEnable(GL_LIGHTING); + glLightfv(GL_LIGHT0, GL_POSITION, cs->position); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse2); + glEnable(GL_LIGHT0); -/* glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient2); */ + /* glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient2); */ - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); - glLightfv(GL_LIGHT1, GL_SPECULAR, diffuse2); - glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse2); - glEnable(GL_LIGHT1); + glLightfv(GL_LIGHT1, GL_SPECULAR, diffuse2); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse2); + glEnable(GL_LIGHT1); +} + +static enum color get_piece_color(int piece) { + if (piece < BKING) + return WHITE; + return BLACK; } /* draw pieces */ -static void drawPieces(ModeInfo *mi, Chesscreen *cs) -{ - int i, j; - - for(i = 0; i < BOARDSIZE; ++i) { - for(j = 0; j < BOARDSIZE; ++j) { - if(cs->game.board[i][j]) { - int c = cs->game.board[i][j]/PIECES; - glColor3fv(cs->colors[c]); - glCallList(cs->game.board[i][j]%PIECES); - mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES]; - } - - glTranslatef(1.0, 0.0, 0.0); - } - - glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0); - } +static void drawPieces(ModeInfo *mi, Chesscreen *cs) { + int i, j; - glTranslatef(0.0, 0.0, -1.0*BOARDSIZE); + for (i = 0; i < BOARDSIZE; ++i) { + for (j = 0; j < BOARDSIZE; ++j) { + if (cs->board[i][j]) { + int c = cs->board[i][j] / PIECES; + int piece = cs->board[i][j] % PIECES; + int side = (cs->board[i][j] == piece ? 1 : -1); + glColor3fv(cs->colors[c]); + if (cs->board[i][j] == KNIGHT) + glRotatef(180.0, 0.0, 1.0, 0.0); + else if (piece == BISHOP) + glRotatef(90.0 * side, 0.0, 1.0, 0.0); + glCallList(piece); + if (cs->board[i][j] == KNIGHT) + glRotatef(180.0, 0.0, 1.0, 0.0); + else if (piece == BISHOP) + glRotatef(-90.0 * side, 0.0, 1.0, 0.0); + mi->polygon_count += cs->poly_counts[cs->board[i][j] % PIECES]; + } + glTranslatef(1.0, 0.0, 0.0); + } + glTranslatef(-1.0 * BOARDSIZE, 0.0, 1.0); + } + glTranslatef(0.0, 0.0, -1.0 * BOARDSIZE); } /* draw pieces */ -static void drawPiecesShadow(ModeInfo *mi, Chesscreen *cs) -{ - int i, j; - - for(i = 0; i < BOARDSIZE; ++i) { - for(j = 0; j < BOARDSIZE; ++j) { - if(cs->game.board[i][j]) { - glColor4f(0.0, 0.0, 0.0, 0.4); - glCallList(cs->game.board[i][j]%PIECES); - mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES]; - } - - glTranslatef(1.0, 0.0, 0.0); - } - - glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0); - } +static void drawPiecesShadow(ModeInfo *mi, Chesscreen *cs) { + int i, j; - glTranslatef(0.0, 0.0, -1.0*BOARDSIZE); + for (i = 0; i < BOARDSIZE; ++i) { + for (j = 0; j < BOARDSIZE; ++j) { + if (cs->board[i][j]) { + glColor4f(0.0, 0.0, 0.0, 0.4); + glCallList(cs->board[i][j] % PIECES); + mi->polygon_count += cs->poly_counts[cs->board[i][j] % PIECES]; + } + glTranslatef(1.0, 0.0, 0.0); + } + glTranslatef(-1.0 * BOARDSIZE, 0.0, 1.0); + } + glTranslatef(0.0, 0.0, -1.0 * BOARDSIZE); } -/* draw a moving piece */ -static void drawMovingPiece(ModeInfo *mi, Chesscreen *cs, int shadow) -{ - int piece = cs->mpiece % PIECES; - - if (piece == NONE) return; +/** Helpers */ +static int char_to_piece(char piece_char) { + switch (piece_char) { + case 'p': + return BPAWN; + case 'P': + return PAWN; + case 'q': + return BQUEEN; + case 'Q': + return QUEEN; + case 'k': + return BKING; + case 'K': + return KING; + case 'b': + return BBISHOP; + case 'B': + return BISHOP; + case 'n': + return BKNIGHT; + case 'N': + return KNIGHT; + case 'r': + return BROOK; + case 'R': + return ROOK; + default: + return NONE; + } + return NONE; +} - glPushMatrix(); +static int get_digit(char c) { + switch (c) { + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + default: + return 0; + } + return 0; +} - if(shadow) glColor4fv(MaterialShadow); - else glColor3fv(cs->colors[cs->mpiece/PIECES]); +static int char_to_rowcol(char c) { + switch (c) { + case 'a': + case '8': + return 0; + case 'b': + case '7': + return 1; + case 'c': + case '6': + return 2; + case 'd': + case '5': + return 3; + case 'e': + case '4': + return 4; + case 'f': + case '3': + return 5; + case 'g': + case '2': + return 6; + case 'h': + case '1': + return 7; + default: + return -1; + } + return -1; +} - /** assume a queening. should be more general */ - if((cs->mpiece == PAWN && fabs(cs->to[0]) < 0.01) || - (cs->mpiece == BPAWN && fabs(cs->to[0]-7.0) < 0.01)) { - glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz); +static void apply_fen(Chesscreen *cs) { + char *row, *saveptr; + char *fen = cs->game.fen; + + row = strtok_r(fen, "/", &saveptr); + for (int row_num = 0; row_num < 8; row_num++) { + int col_num = 0; + for (int char_num = 0; char_num < strlen(row); char_num++) { + char c = row[char_num]; + int d = get_digit(c); + for (int i = 0; i < d; i++) { + cs->board[row_num][col_num++] = NONE; + } + int p = char_to_piece(c); + if (p != NONE) { + cs->board[row_num][col_num++] = p; + } + } + row = strtok_r(NULL, "/", &saveptr); + } +} - glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->mpiece/7][0], - shadow ? MaterialShadow[1] : cs->colors[cs->mpiece/7][1], - shadow ? MaterialShadow[2] : cs->colors[cs->mpiece/7][2], - (fabs(50.0-cs->steps))/50.0); +static void coord_to_case(char *uci, int chess_case[2]) { + chess_case[0] = char_to_rowcol(uci[1]); + chess_case[1] = char_to_rowcol(uci[0]); +} - piece = cs->steps < 50 ? PAWN : QUEEN; +static int color_piece(int piece, enum color color) { + if (piece == NONE) + return piece; + if (color == WHITE) + return piece % PIECES; + return (piece % PIECES) + PIECES; +} - /* what a kludge */ - if(cs->steps == 99) - cs->mpiece = cs->mpiece == PAWN ? QUEEN : BQUEEN; - } - else if(cs->mpiece % PIECES == KNIGHT) { - /* If there is nothing in the path of a knight, move it by sliding, - just like the other pieces. But if there are any pieces on the - middle two squares in its path, the knight would intersect them, - so in that case, move it in an airborne arc. */ - GLfloat y; - int i, j; - Bool blocked_p = False; - int fromx = MIN(cs->from[1], cs->to[1]); - int fromy = MIN(cs->from[0], cs->to[0]); - int tox = MAX(cs->from[1], cs->to[1]); - int toy = MAX(cs->from[0], cs->to[0]); - if (fromx == tox-2) fromx = tox = fromx+1; - if (fromy == toy-2) fromy = toy = fromy+1; - for (i = fromy; i <= toy; i++) { - for (j = fromx; j <= tox; j++) { - if (cs->game.board[i][j]) { - blocked_p = True; - break; +static void setup_move(Chesscreen *cs, char *uci, int move_index) { + Chessmovestate *movestate = &(cs->moves[move_index]); + coord_to_case(uci, movestate->from); + coord_to_case(uci + 2, movestate->to); + movestate->mpiece = cs->board[movestate->from[0]][movestate->from[1]]; + movestate->color = get_piece_color(movestate->mpiece); + if (strlen(uci) == 5) + movestate->promotion = + color_piece(char_to_piece(uci[4]), movestate->color); + movestate->dz = (movestate->to[0] - movestate->from[0]) / num_steps_f; + movestate->dx = (movestate->to[1] - movestate->from[1]) / num_steps_f; + cs->board[movestate->from[0]][movestate->from[1]] = + NONE; /* Remove moving piece from board */ + + movestate->tpiece = cs->board[movestate->to[0]][movestate->to[1]]; + /* Capture ? */ + if (movestate->tpiece != NONE) { + cs->board[movestate->to[0]][movestate->to[1]] = + NONE; /* Remove captured piece from board */ + movestate->en_passant[0] = movestate->en_passant[1] = + -1; /* Not en passant */ + } else { /* Destination case is empty. Is this an en passant capture ? */ + /* White en passant ? */ + if ((movestate->mpiece == PAWN) && (movestate->from[0] == 3) && + (movestate->from[1] != movestate->to[1])) { + movestate->tpiece = BPAWN; + movestate->en_passant[0] = 3; + movestate->en_passant[1] = movestate->to[1]; + cs->board[movestate->en_passant[0]][movestate->en_passant[1]] = + NONE; /* Remove captured piece */ + } + /* Black en passant ? */ + else if ((movestate->mpiece == BPAWN) && (movestate->from[0] == 4) && + (movestate->from[1] != movestate->to[1])) { + movestate->tpiece = PAWN; + movestate->en_passant[0] = 4; + movestate->en_passant[1] = movestate->to[1]; + cs->board[movestate->en_passant[0]][movestate->en_passant[1]] = + NONE; /* Remove captured piece */ } - } } + movestate->active = 1; +} - if (!blocked_p) - goto SLIDE; +static void setup_moves(Chesscreen *cs, char *uci) { + setup_move(cs, uci, 0); /* General case */ + if (!strncmp(uci, "e1g1", 4)) { /* White king castling */ + setup_move(cs, "h1f1", 1); /* rook will move at the same time */ + cs->moves[1].castling = 1; + return; + } + if (!strncmp(uci, "e1c1", 4)) { /* White queen castling */ + setup_move(cs, "a1d1", 1); /* rook will move at the same time */ + cs->moves[1].castling = 1; + return; + } + if (!strncmp(uci, "e8g8", 4)) { /* Black king castling */ + setup_move(cs, "h8f8", 1); /* rook will move at the same time */ + cs->moves[1].castling = 1; + return; + } + if (!strncmp(uci, "e8c8", 4)) { /* Black queen castling */ + setup_move(cs, "a8d8", 1); /* rook will move at the same time */ + cs->moves[1].castling = 1; + return; + } +} - /* Move by hopping. */ - y = 1.5 * sin (M_PI * cs->steps / 100.0); - glTranslatef(cs->from[1]+cs->steps*cs->dx, y, - cs->from[0]+cs->steps*cs->dz); +static int are_moves_active(Chesscreen *cs) { + for (int i = 0; i < CONCURRENT_MOVES; i++) { + if (cs->moves[i].active) + return 1; + } + return 0; +} - } else { - SLIDE: - /* Move by sliding. */ - glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz); - } +static int is_a_piece_taken(Chesscreen *cs) { + for (int i = 0; i < CONCURRENT_MOVES; i++) { + if (cs->moves[i].tpiece != NONE) + return 1; + } + return 0; +} +static void init_moves(Chesscreen *cs) { + for (int i = 0; i < CONCURRENT_MOVES; i++) { + cs->moves[i].active = 0; + cs->moves[i].tpiece = cs->moves[i].mpiece = NONE; + cs->moves[i].promotion = NONE; + cs->moves[i].en_passant[0] = cs->moves[i].en_passant[1] = -1; + cs->moves[i].color = WHITE; + cs->moves[i].dx = cs->moves[i].dz = 0; + cs->moves[i].castling = 0; + } +} - if(!cs->wire) - glEnable(GL_BLEND); - - glCallList(piece); - mi->polygon_count += cs->poly_counts[cs->mpiece % PIECES]; +static double +ease_move (double x, double max) +{ + if (max == 0) return x; + if (max < 0) max = -max; + if (x > 0) + return max * ease (EASE_IN_OUT_CUBIC, x / max); + else + return max * -ease (EASE_IN_OUT_CUBIC, -x / max); +} - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); - glPopMatrix(); +/* draw a moving piece */ +static void drawMovingPiece(ModeInfo *mi, Chesscreen *cs, int shadow) { + int piece, side, promotion_piece; + + for (int i = 0; i < CONCURRENT_MOVES; i++) { + Chessmovestate *movestate = &(cs->moves[i]); + if (!movestate->active) + continue; + piece = movestate->mpiece % PIECES; + side = (movestate->color == WHITE ? 1 : -1); + if (piece == NONE) + continue; + promotion_piece = movestate->promotion; + + glPushMatrix(); + + if (shadow) + glColor4fv(MaterialShadow); + else + glColor3fv(cs->colors[movestate->mpiece / PIECES]); + + if ((movestate->mpiece == PAWN && abs(movestate->to[0]) < 0.01) || + (movestate->mpiece == BPAWN && + fabs(movestate->to[0] - 7.0) < 0.01)) { + glTranslatef(movestate->from[1] + cs->steps * movestate->dx, 0.0, + movestate->from[0] + cs->steps * movestate->dz); + glColor4f(shadow ? MaterialShadow[0] + : cs->colors[movestate->mpiece / 7][0], + shadow ? MaterialShadow[1] + : cs->colors[movestate->mpiece / 7][1], + shadow ? MaterialShadow[2] + : cs->colors[movestate->mpiece / 7][2], + fabs((num_steps_f / 2.0) - cs->steps) / + (num_steps_f / 2.0)); + + piece = cs->steps < NUM_STEPS / 2 ? PAWN : promotion_piece % PIECES; + + /* what a kludge */ + if (cs->steps == NUM_STEPS - 1) + movestate->mpiece = promotion_piece; + } else if (movestate->mpiece % PIECES == KNIGHT) { + /* If there is nothing in the path of a knight, move it by sliding, + just like the other pieces. But if there are any pieces on the + middle two squares in its path, the knight would intersect them, + so in that case, move it in an airborne arc. */ + GLfloat y; + int i, j; + Bool blocked_p = False; + int fromx = MIN(movestate->from[1], movestate->to[1]); + int fromy = MIN(movestate->from[0], movestate->to[0]); + int tox = MAX(movestate->from[1], movestate->to[1]); + int toy = MAX(movestate->from[0], movestate->to[0]); + if (fromx == tox - 2) + fromx = tox = fromx + 1; + if (fromy == toy - 2) + fromy = toy = fromy + 1; + for (i = fromy; i <= toy; i++) { + for (j = fromx; j <= tox; j++) { + if (cs->board[i][j]) { + blocked_p = True; + break; + } + } + } + + if (!blocked_p) + goto SLIDE; + + /* Move by hopping. */ + y = 1.5 * sin(M_PI * cs->steps / num_steps_f); + glTranslatef(movestate->from[1] + + ease_move (cs->steps * movestate->dx, + movestate->to[1] - movestate->from[1]), + y, + movestate->from[0] + + ease_move (cs->steps * movestate->dz, + movestate->to[0] - movestate->from[0])); + + } else if ((movestate->mpiece % PIECES == ROOK) && + movestate->castling) { + /* Move z in an arc */ + GLfloat offset = 1.5 * sin(M_PI * cs->steps / num_steps_f); + glTranslatef(movestate->from[1] + + ease_move (cs->steps * movestate->dx, + movestate->to[1] - movestate->from[1]), + 0.0, + movestate->from[0] + + ease_move (cs->steps * movestate->dz + + (movestate->color == WHITE + ? offset : -offset), + movestate->to[0] - movestate->from[0])); + } else { + SLIDE: + /* Move by sliding. */ + glTranslatef(movestate->from[1] + + ease_move (cs->steps * movestate->dx, + movestate->to[1] - movestate->from[1]), + 0.0, + movestate->from[0] + + ease_move (cs->steps * movestate->dz, + movestate->to[0] - movestate->from[0])); + } - if(!cs->wire) - glDisable(GL_BLEND); + if (!cs->wire) + glEnable(GL_BLEND); + + if ((movestate->mpiece == KNIGHT) || + ((promotion_piece == KNIGHT) && (cs->steps >= NUM_STEPS / 2))) + glRotatef(180.0, 0.0, 1.0, 0.0); + if ((piece == BISHOP) || + ((promotion_piece == BISHOP) && (cs->steps >= NUM_STEPS / 2))) + glRotatef(90.0 * side, 0.0, 1.0, 0.0); + glCallList(piece); + if ((movestate->mpiece == KNIGHT) || + ((promotion_piece == KNIGHT) && (cs->steps >= NUM_STEPS / 2))) + glRotatef(180.0, 0.0, 1.0, 0.0); + if ((piece == BISHOP) || + ((promotion_piece == BISHOP) && (cs->steps >= NUM_STEPS / 2))) + glRotatef(-90.0 * side, 0.0, 1.0, 0.0); + mi->polygon_count += cs->poly_counts[movestate->mpiece % PIECES]; + + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); + + glPopMatrix(); + + if (!cs->wire) + glDisable(GL_BLEND); + } } /** code to squish a taken piece */ -static void drawTakePiece(ModeInfo *mi, Chesscreen *cs, int shadow) -{ - if(!cs->wire) - glEnable(GL_BLEND); - - glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->tpiece/7][0], - shadow ? MaterialShadow[1] : cs->colors[cs->tpiece/7][1], - shadow ? MaterialShadow[2] : cs->colors[cs->tpiece/7][2], - (100-1.6*cs->steps)/100.0); - - glTranslatef(cs->to[1], 0.0, cs->to[0]); - - if(cs->mpiece % PIECES == KNIGHT) - glScalef(1.0+cs->steps/100.0, 1.0, 1.0+cs->steps/100.0); - else - glScalef(1.0, 1 - cs->steps/50.0 > 0.01 ? 1 - cs->steps/50.0 : 0.01, 1.0); - glCallList(cs->tpiece % 7); - mi->polygon_count += cs->poly_counts[cs->tpiece % PIECES]; - - if(!cs->wire) - glDisable(GL_BLEND); -} +static void drawTakePiece(ModeInfo *mi, Chesscreen *cs, int shadow) { + if (!cs->wire) + glEnable(GL_BLEND); + + /* Only the first move can take a piece in case of multiple + * concurrent moves (castling). So we could only consider the first move + * for capture... but let's loop anyway over all concurrent moves since it + * costs almost nothing */ + for (int i = 0; i < CONCURRENT_MOVES; i++) { + Chessmovestate *movestate = &(cs->moves[i]); + int side = (movestate->color == BLACK ? 1 : -1); + if (!movestate->active) + continue; + + glColor4f( + shadow ? MaterialShadow[0] : cs->colors[movestate->tpiece / 7][0], + shadow ? MaterialShadow[1] : cs->colors[movestate->tpiece / 7][1], + shadow ? MaterialShadow[2] : cs->colors[movestate->tpiece / 7][2], + (num_steps_f - 1.6 * cs->steps) / num_steps_f); + + if (movestate->en_passant[0] != -1) { + glTranslatef(movestate->en_passant[1], 0.0, + movestate->en_passant[0]); + } else { + glTranslatef(movestate->to[1], 0.0, movestate->to[0]); + } -/** draw board */ -static void drawBoard(ModeInfo *mi, Chesscreen *cs) -{ - int i, j; - - glBegin(GL_QUADS); - - for(i = 0; i < BOARDSIZE; ++i) - for(j = 0; j < BOARDSIZE; ++j) { - double ma1 = (i+j)%2 == 0 ? cs->mod*i : 0.0; - double mb1 = (i+j)%2 == 0 ? cs->mod*j : 0.0; - double ma2 = (i+j)%2 == 0 ? cs->mod*(i+1.0) : 0.01; - double mb2 = (i+j)%2 == 0 ? cs->mod*(j+1.0) : 0.01; - - /*glColor3fv(colors[(i+j)%2]);*/ - glColor4f(cs->colors[(i+j)%2][0], cs->colors[(i+j)%2][1], - cs->colors[(i+j)%2][2], 0.65); - - glNormal3f(0.0, 1.0, 0.0); -/* glTexCoord2f(mod*i, mod*(j+1.0)); */ - glTexCoord2f(ma1, mb2); - glVertex3f(i, 0.0, j + 1.0); -/* glTexCoord2f(mod*(i+1.0), mod*(j+1.0)); */ - glTexCoord2f(ma2, mb2); - glVertex3f(i + 1.0, 0.0, j + 1.0); - glTexCoord2f(ma2, mb1); -/* glTexCoord2f(mod*(i+1.0), mod*j); */ - glVertex3f(i + 1.0, 0.0, j); - glTexCoord2f(ma1, mb1); -/* glTexCoord2f(mod*i, mod*j); */ - glVertex3f(i, 0.0, j); - - mi->polygon_count++; + if (movestate->tpiece % PIECES == KNIGHT) + glScalef(1.0 + cs->steps / num_steps_f, 1.0, + 1.0 + cs->steps / num_steps_f); + else + glScalef(1.0, + 1.0 - cs->steps / num_steps_f / 2 > 0.01 + ? 1.0 - cs->steps / num_steps_f + : 0.01, + 1.0); + + if (movestate->tpiece == KNIGHT) + glRotatef(180.0, 0.0, 1.0, 0.0); + else if ((movestate->tpiece % PIECES) == BISHOP) + glRotatef(90.0 * side, 0.0, 1.0, 0.0); + glCallList(movestate->tpiece % 7); + if (movestate->tpiece == KNIGHT) + glRotatef(180.0, 0.0, 1.0, 0.0); + else if ((movestate->tpiece % PIECES) == BISHOP) + glRotatef(-90.0 * side, 0.0, 1.0, 0.0); + mi->polygon_count += cs->poly_counts[movestate->tpiece % PIECES]; } - glEnd(); - - { - GLfloat off = 0.01; - GLfloat w = BOARDSIZE; - GLfloat h = 0.1; - - /* Give the board a slight lip. */ - /* #### oops, normals are wrong here, but you can't tell */ - - glColor3f(0.3, 0.3, 0.3); - glBegin (GL_QUADS); - glVertex3f (0, 0, 0); - glVertex3f (0, -h, 0); - glVertex3f (0, -h, w); - glVertex3f (0, 0, w); - - glVertex3f (0, 0, w); - glVertex3f (0, -h, w); - glVertex3f (w, -h, w); - glVertex3f (w, 0, w); - - glVertex3f (w, 0, w); - glVertex3f (w, -h, w); - glVertex3f (w, -h, 0); - glVertex3f (w, 0, 0); - - glVertex3f (w, 0, 0); - glVertex3f (w, -h, 0); - glVertex3f (0, -h, 0); - glVertex3f (0, 0, 0); - - glVertex3f (0, -h, 0); - glVertex3f (w, -h, 0); - glVertex3f (w, -h, w); - glVertex3f (0, -h, w); - glEnd(); - mi->polygon_count += 4; - - /* Fill in the underside of the board with an invisible black box - to hide the reflections that are not on tiles. Probably there's - a way to do this with stencils instead. - */ - w -= off*2; - h = 5; - glPushMatrix(); - glTranslatef (off, 0, off); - glDisable(GL_LIGHTING); - glColor3f(0,0,0); - glBegin (GL_QUADS); - glVertex3f (0, 0, 0); - glVertex3f (0, -h, 0); - glVertex3f (0, -h, w); - glVertex3f (0, 0, w); - - glVertex3f (0, 0, w); - glVertex3f (0, -h, w); - glVertex3f (w, -h, w); - glVertex3f (w, 0, w); - - glVertex3f (w, 0, w); - glVertex3f (w, -h, w); - glVertex3f (w, -h, 0); - glVertex3f (w, 0, 0); - - glVertex3f (w, 0, 0); - glVertex3f (w, -h, 0); - glVertex3f (0, -h, 0); - glVertex3f (0, 0, 0); - - glVertex3f (0, -h, 0); - glVertex3f (w, -h, 0); - glVertex3f (w, -h, w); - glVertex3f (0, -h, w); - glEnd(); - mi->polygon_count += 4; - glPopMatrix(); if (!cs->wire) - glEnable(GL_LIGHTING); - } + glDisable(GL_BLEND); } -static void draw_pieces(ModeInfo *mi, Chesscreen *cs, int wire) -{ - if (!cs->wire) { - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, cs->piecetexture); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +/** draw board */ +static void drawBoard(ModeInfo *mi, Chesscreen *cs) { + int i, j; - glColor4f(0.5, 0.5, 0.5, 1.0); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); - } + glBegin(GL_QUADS); + + for (i = 0; i < BOARDSIZE; ++i) + for (j = 0; j < BOARDSIZE; ++j) { + double ma1 = (i + j) % 2 == 0 ? cs->mod * i : 0.0; + double mb1 = (i + j) % 2 == 0 ? cs->mod * j : 0.0; + double ma2 = (i + j) % 2 == 0 ? cs->mod * (i + 1.0) : 0.01; + double mb2 = (i + j) % 2 == 0 ? cs->mod * (j + 1.0) : 0.01; + + /*glColor3fv(colors[(i+j)%2]);*/ + glColor4f(cs->colors[(i + j) % 2][0], cs->colors[(i + j) % 2][1], + cs->colors[(i + j) % 2][2], 0.65); + + glNormal3f(0.0, 1.0, 0.0); + /* glTexCoord2f(mod*i, mod*(j+1.0)); */ + glTexCoord2f(ma1, mb2); + glVertex3f(i, 0.0, j + 1.0); + /* glTexCoord2f(mod*(i+1.0), mod*(j+1.0)); */ + glTexCoord2f(ma2, mb2); + glVertex3f(i + 1.0, 0.0, j + 1.0); + glTexCoord2f(ma2, mb1); + /* glTexCoord2f(mod*(i+1.0), mod*j); */ + glVertex3f(i + 1.0, 0.0, j); + glTexCoord2f(ma1, mb1); + /* glTexCoord2f(mod*i, mod*j); */ + glVertex3f(i, 0.0, j); + + mi->polygon_count++; + } + glEnd(); - drawPieces(mi, cs); - if(cs->moving) drawMovingPiece(mi, cs, 0); - if(cs->take) drawTakePiece(mi, cs, 0); - glDisable(GL_TEXTURE_2D); + { + GLfloat off = 0.01; + GLfloat w = BOARDSIZE; + GLfloat h = 0.1; + + /* Give the board a slight lip. */ + /* #### oops, normals are wrong here, but you can't tell */ + + glColor3f(0.3, 0.3, 0.3); + glBegin(GL_QUADS); + glVertex3f(0, 0, 0); + glVertex3f(0, -h, 0); + glVertex3f(0, -h, w); + glVertex3f(0, 0, w); + + glVertex3f(0, 0, w); + glVertex3f(0, -h, w); + glVertex3f(w, -h, w); + glVertex3f(w, 0, w); + + glVertex3f(w, 0, w); + glVertex3f(w, -h, w); + glVertex3f(w, -h, 0); + glVertex3f(w, 0, 0); + + glVertex3f(w, 0, 0); + glVertex3f(w, -h, 0); + glVertex3f(0, -h, 0); + glVertex3f(0, 0, 0); + + glVertex3f(0, -h, 0); + glVertex3f(w, -h, 0); + glVertex3f(w, -h, w); + glVertex3f(0, -h, w); + glEnd(); + mi->polygon_count += 4; + + /* Fill in the underside of the board with an invisible black box + to hide the reflections that are not on tiles. Probably there's + a way to do this with stencils instead. + */ + w -= off * 2; + h = 5; + + glPushMatrix(); + glTranslatef(off, 0, off); + glDisable(GL_LIGHTING); + glColor3f(0, 0, 0); + glBegin(GL_QUADS); + glVertex3f(0, 0, 0); + glVertex3f(0, -h, 0); + glVertex3f(0, -h, w); + glVertex3f(0, 0, w); + + glVertex3f(0, 0, w); + glVertex3f(0, -h, w); + glVertex3f(w, -h, w); + glVertex3f(w, 0, w); + + glVertex3f(w, 0, w); + glVertex3f(w, -h, w); + glVertex3f(w, -h, 0); + glVertex3f(w, 0, 0); + + glVertex3f(w, 0, 0); + glVertex3f(w, -h, 0); + glVertex3f(0, -h, 0); + glVertex3f(0, 0, 0); + + glVertex3f(0, -h, 0); + glVertex3f(w, -h, 0); + glVertex3f(w, -h, w); + glVertex3f(0, -h, w); + glEnd(); + mi->polygon_count += 4; + glPopMatrix(); + if (!cs->wire) + glEnable(GL_LIGHTING); + } } -static void draw_shadow_pieces(ModeInfo *mi, Chesscreen *cs, int wire) -{ - if (!cs->wire) { - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, cs->piecetexture); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - - /* use the stencil */ - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - glDisable(GL_DEPTH_TEST); - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); +static void draw_pieces(ModeInfo *mi, Chesscreen *cs, int wire) { + if (!cs->wire) { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, cs->piecetexture); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glClear(GL_STENCIL_BUFFER_BIT); - glColorMask(0,0,0,0); - glEnable(GL_STENCIL_TEST); + glColor4f(0.5, 0.5, 0.5, 1.0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); + } - glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFFL); - glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); - + drawPieces(mi, cs); + if (are_moves_active(cs)) + drawMovingPiece(mi, cs, 0); + if (is_a_piece_taken(cs)) + drawTakePiece(mi, cs, 0); + glDisable(GL_TEXTURE_2D); +} - glPushMatrix(); - glTranslatef(0.0, 0.001, 0.0); +static void draw_shadow_pieces(ModeInfo *mi, Chesscreen *cs, int wire) { + if (!cs->wire) { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, cs->piecetexture); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } - /* draw the pieces */ - drawPiecesShadow(mi, cs); - if(cs->moving) drawMovingPiece(mi, cs, shadows); - if(cs->take) drawTakePiece(mi, cs, shadows); + /* use the stencil */ + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_DEPTH_TEST); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); - glPopMatrix(); + glClear(GL_STENCIL_BUFFER_BIT); + glColorMask(0, 0, 0, 0); + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFFL); + glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); - /* turn on drawing into colour buffer */ - glColorMask(1,1,1,1); + glPushMatrix(); + glTranslatef(0.0, 0.001, 0.0); - /* programming with effect */ - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - glDisable(GL_TEXTURE_2D); + /* draw the pieces */ + drawPiecesShadow(mi, cs); + if (are_moves_active(cs)) + drawMovingPiece(mi, cs, shadows); + if (is_a_piece_taken(cs)) + drawTakePiece(mi, cs, shadows); - /* now draw the union of the shadows */ + glPopMatrix(); - /* - - want to keep alpha values (alpha is involved in transition - effects of the active pieces). - - */ - glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFFL); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + /* turn on drawing into colour buffer */ + glColorMask(1, 1, 1, 1); - glEnable(GL_BLEND); + /* programming with effect */ + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_TEXTURE_2D); - glColor4fv(MaterialShadow); + /* now draw the union of the shadows */ - /* draw the board generously to fill the shadows */ - glBegin(GL_QUADS); + /* + + want to keep alpha values (alpha is involved in transition + effects of the active pieces). + + */ + glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFFL); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glVertex3f(-1.0, 0.0, -1.0); - glVertex3f(-1.0, 0.0, BOARDSIZE + 1.0); - glVertex3f(1.0 + BOARDSIZE, 0.0, BOARDSIZE + 1.0); - glVertex3f(1.0 + BOARDSIZE, 0.0, -1.0); + glEnable(GL_BLEND); - glEnd(); + glColor4fv(MaterialShadow); - glDisable(GL_STENCIL_TEST); + /* draw the board generously to fill the shadows */ + glBegin(GL_QUADS); - /* "pop" attributes */ - glEnable(GL_TEXTURE_2D); - glEnable(GL_COLOR_MATERIAL); - glEnable(GL_LIGHTING); - glEnable(GL_CULL_FACE); + glVertex3f(-1.0, 0.0, -1.0); + glVertex3f(-1.0, 0.0, BOARDSIZE + 1.0); + glVertex3f(1.0 + BOARDSIZE, 0.0, BOARDSIZE + 1.0); + glVertex3f(1.0 + BOARDSIZE, 0.0, -1.0); + glEnd(); + glDisable(GL_STENCIL_TEST); + /* "pop" attributes */ + glEnable(GL_TEXTURE_2D); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_LIGHTING); + glEnable(GL_CULL_FACE); } -enum {X, Y, Z, W}; -enum {A, B, C, D}; +enum { X, Y, Z, W }; +enum { A, B, C, D }; /* create a matrix that will project the desired shadow */ -static void shadowmatrix(GLfloat shadowMat[4][4], - GLfloat groundplane[4], - GLfloat lightpos[4]) -{ - GLfloat dot; - - /* find dot product between light position vector and ground plane normal */ - dot = groundplane[X] * lightpos[X] + - groundplane[Y] * lightpos[Y] + - groundplane[Z] * lightpos[Z] + - groundplane[W] * lightpos[W]; - - shadowMat[0][0] = dot - lightpos[X] * groundplane[X]; - shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y]; - shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z]; - shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W]; - - shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X]; - shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y]; - shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z]; - shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W]; - - shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X]; - shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y]; - shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z]; - shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W]; - - shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X]; - shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y]; - shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z]; - shadowMat[3][3] = dot - lightpos[W] * groundplane[W]; +static void shadowmatrix(GLfloat shadowMat[4][4], GLfloat groundplane[4], + GLfloat lightpos[4]) { + GLfloat dot; + + /* find dot product between light position vector and ground plane normal */ + dot = groundplane[X] * lightpos[X] + groundplane[Y] * lightpos[Y] + + groundplane[Z] * lightpos[Z] + groundplane[W] * lightpos[W]; + + shadowMat[0][0] = dot - lightpos[X] * groundplane[X]; + shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y]; + shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z]; + shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W]; + + shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X]; + shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y]; + shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z]; + shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W]; + + shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X]; + shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y]; + shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z]; + shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W]; + + shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X]; + shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y]; + shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z]; + shadowMat[3][3] = dot - lightpos[W] * groundplane[W]; } /** reflectionboard */ -static void draw_reflections(ModeInfo *mi, Chesscreen *cs) -{ - int i, j; - - glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_ALWAYS, 1, 1); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glColorMask(0,0,0,0); - glDisable(GL_CULL_FACE); - - glDisable(GL_DEPTH_TEST); - glBegin(GL_QUADS); - - /* only draw white squares */ - for(i = 0; i < BOARDSIZE; ++i) { - for(j = (BOARDSIZE+i) % 2; j < BOARDSIZE; j += 2) { - glVertex3f(i, 0.0, j + 1.0); - glVertex3f(i + 1.0, 0.0, j + 1.0); - glVertex3f(i + 1.0, 0.0, j); - glVertex3f(i, 0.0, j); - mi->polygon_count++; - } - } - glEnd(); - glEnable(GL_DEPTH_TEST); - - glColorMask(1, 1, 1, 1); - glStencilFunc(GL_EQUAL, 1, 1); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - - glPushMatrix(); - glScalef(1.0, -1.0, 1.0); - glTranslatef(0.5, 0.0, 0.5); - - glLightfv(GL_LIGHT0, GL_POSITION, cs->position); - draw_pieces(mi, cs, cs->wire); - glPopMatrix(); - - glDisable(GL_STENCIL_TEST); - glLightfv(GL_LIGHT0, GL_POSITION, cs->position); - - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - glColorMask(1,1,1,1); -} - -/** draws the scene */ -static void display(ModeInfo *mi, Chesscreen *cs) -{ - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - mi->polygon_count = 0; - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glRotatef(current_device_rotation(), 0, 0, 1); - - /** setup perspectiv */ - glTranslatef(0.0, 0.0, -1.5*BOARDSIZE); - glRotatef(30.0, 1.0, 0.0, 0.0); - gltrackball_rotate (cs->trackball); +static void draw_reflections(ModeInfo *mi, Chesscreen *cs) { + int i, j; - if (rotate) - glRotatef(cs->theta*100, 0.0, 1.0, 0.0); - glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE); + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 1); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glColorMask(0, 0, 0, 0); + glDisable(GL_CULL_FACE); + + glDisable(GL_DEPTH_TEST); + glBegin(GL_QUADS); + + /* only draw white squares */ + for (i = 0; i < BOARDSIZE; ++i) { + for (j = (BOARDSIZE + i) % 2; j < BOARDSIZE; j += 2) { + glVertex3f(i, 0.0, j + 1.0); + glVertex3f(i + 1.0, 0.0, j + 1.0); + glVertex3f(i + 1.0, 0.0, j); + glVertex3f(i, 0.0, j); + mi->polygon_count++; + } + } + glEnd(); + glEnable(GL_DEPTH_TEST); -/* cs->position[0] = 4.0 + 1.0*-sin(cs->theta*100*M_PI/180.0); */ -/* cs->position[2] = 4.0 + 1.0* cos(cs->theta*100*M_PI/180.0); */ -/* cs->position[1] = 5.0; */ + glColorMask(1, 1, 1, 1); + glStencilFunc(GL_EQUAL, 1, 1); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - /* this is the lone light that the shadow matrix is generated from */ - cs->position[0] = 1.0; - cs->position[2] = 1.0; - cs->position[1] = 16.0; + glPushMatrix(); + glScalef(1.0, -1.0, 1.0); + glTranslatef(0.5, 0.0, 0.5); - cs->position2[0] = 4.0 + 8.0*-sin(cs->theta*100*M_PI/180.0); - cs->position2[2] = 4.0 + 8.0* cos(cs->theta*100*M_PI/180.0); + glLightfv(GL_LIGHT0, GL_POSITION, cs->position); + draw_pieces(mi, cs, cs->wire); + glPopMatrix(); - if (!cs->wire) { - glEnable(GL_LIGHTING); + glDisable(GL_STENCIL_TEST); glLightfv(GL_LIGHT0, GL_POSITION, cs->position); - glLightfv(GL_LIGHT1, GL_POSITION, cs->position2); - glEnable(GL_LIGHT0); - } - /** draw board, pieces */ - if(!cs->wire) { - glEnable(GL_LIGHTING); - glEnable(GL_COLOR_MATERIAL); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glColorMask(1, 1, 1, 1); +} - if(reflections && !cs->wire) { - draw_reflections(mi, cs); - glEnable(GL_BLEND); - } +/** draws the scene */ +static void display(ModeInfo *mi, Chesscreen *cs) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, cs->boardtexture); - drawBoard(mi, cs); - glDisable(GL_TEXTURE_2D); + mi->polygon_count = 0; - if(shadows) { - /* render shadows */ - GLfloat m[4][4]; - shadowmatrix(m, cs->ground, cs->position); - - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); - glEnable(GL_BLEND); - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - - /* display ant shadow */ - glPushMatrix(); - glTranslatef(0.0, 0.001, 0.0); - glMultMatrixf(m[0]); - glTranslatef(0.5, 0.01, 0.5); - draw_shadow_pieces(mi, cs, cs->wire); - glPopMatrix(); - - glEnable(GL_LIGHTING); - glDisable(GL_BLEND); - glEnable(GL_DEPTH_TEST); - } + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glRotatef(current_device_rotation(), 0, 0, 1); - if(reflections) - glDisable(GL_BLEND); - } - else - drawBoard(mi, cs); - - glTranslatef(0.5, 0.0, 0.5); - draw_pieces(mi, cs, cs->wire); + /** setup perspectiv */ + glTranslatef(0.0, 0.0, -1.5 * BOARDSIZE); + glRotatef(30.0, 1.0, 0.0, 0.0); + gltrackball_rotate(cs->trackball); - if(!cs->wire) { - glDisable(GL_COLOR_MATERIAL); - glDisable(GL_LIGHTING); - } + if (rotate) + glRotatef(cs->theta * 100, 0.0, 1.0, 0.0); + glTranslatef(-0.5 * BOARDSIZE, 0.0, -0.5 * BOARDSIZE); - if (!cs->button_down_p) - cs->theta += .002; -} + /* cs->position[0] = 4.0 + 1.0*-sin(cs->theta*100*M_PI/180.0); */ + /* cs->position[2] = 4.0 + 1.0* cos(cs->theta*100*M_PI/180.0); */ + /* cs->position[1] = 5.0; */ -/** reshape handler */ -ENTRYPOINT void reshape_chess(ModeInfo *mi, int width, int height) -{ - GLfloat h = (GLfloat) height / (GLfloat) width; - int y = 0; + /* this is the lone light that the shadow matrix is generated from */ + cs->position[0] = 1.0; + cs->position[2] = 1.0; + cs->position[1] = 16.0; - if (width > height * 5) { /* tiny window: show middle */ - height = width * 9/16; - y = -height/2; - h = height / (GLfloat) width; - } + cs->position2[0] = 4.0 + 8.0 * -sin(cs->theta * 100 * M_PI / 180.0); + cs->position2[2] = 4.0 + 8.0 * cos(cs->theta * 100 * M_PI / 180.0); - glViewport(0,y, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(45, 1/h, 2.0, 30.0); - glMatrixMode(GL_MODELVIEW); -} + if (!cs->wire) { + glEnable(GL_LIGHTING); + glLightfv(GL_LIGHT0, GL_POSITION, cs->position); + glLightfv(GL_LIGHT1, GL_POSITION, cs->position2); + glEnable(GL_LIGHT0); + } -/** initialization handler */ -ENTRYPOINT void init_chess(ModeInfo *mi) -{ - Chesscreen *cs; - int screen = MI_SCREEN(mi); + /** draw board, pieces */ + if (!cs->wire) { + glEnable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); - MI_INIT(mi, qs); - - cs = &qs[screen]; - cs->window = MI_WINDOW(mi); - cs->wire = MI_IS_WIREFRAME(mi); - cs->trackball = gltrackball_init (False); - - cs->oldwhite = -1; + if (reflections && !cs->wire) { + draw_reflections(mi, cs); + glEnable(GL_BLEND); + } - cs->colors[0][0] = 1.0; - cs->colors[0][1] = 0.5; - cs->colors[0][2] = 0.0; + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, cs->boardtexture); + drawBoard(mi, cs); + glDisable(GL_TEXTURE_2D); + + if (shadows) { + /* render shadows */ + GLfloat m[4][4]; + shadowmatrix(m, cs->ground, cs->position); + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); + glEnable(GL_BLEND); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + /* display shadow */ + glPushMatrix(); + glTranslatef(0.0, 0.001, 0.0); + glMultMatrixf(m[0]); + glTranslatef(0.5, 0.01, 0.5); + draw_shadow_pieces(mi, cs, cs->wire); + glPopMatrix(); + + glEnable(GL_LIGHTING); + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + } - cs->colors[1][0] = 0.6; - cs->colors[1][1] = 0.6; - cs->colors[1][2] = 0.6; + if (reflections) + glDisable(GL_BLEND); + } else + drawBoard(mi, cs); - cs->done = 1; - cs->count = 99; - cs->mod = 1.4; + glTranslatef(0.5, 0.0, 0.5); + draw_pieces(mi, cs, cs->wire); -/* cs->position[0] = 0.0; */ -/* cs->position[1] = 5.0; */ -/* cs->position[2] = 5.0; */ -/* cs->position[3] = 1.0; */ + if (!cs->wire) { + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_LIGHTING); + } - cs->position[0] = 0.0; - cs->position[1] = 24.0; - cs->position[2] = 2.0; - cs->position[3] = 1.0; + if (!cs->button_down_p) + cs->theta += .002; +} +static void load_fonts(ModeInfo *mi) { + Chesscreen *cs = &qs[MI_SCREEN(mi)]; + cs->font1_data = load_texture_font(mi->dpy, "titleFont"); + cs->font2_data = load_texture_font(mi->dpy, "titleFont2"); + cs->font3_data = load_texture_font(mi->dpy, "titleFont3"); +} - cs->position2[0] = 5.0; - cs->position2[1] = 5.0; - cs->position2[2] = 5.0; - cs->position2[3] = 1.0; +static void set_description(Chesscreen *cs) { + int move_index; - cs->ground[0] = 0.0; - cs->ground[1] = 1.0; - cs->ground[2] = 0.0; - cs->ground[3] = -0.00001; + if (!labels) + return; - cs->oldgame = -1; + for (int i = 0; i < DESC_STR_LEN + SAN_STR_LEN + 1; i++) + cs->game_desc[i] = cs->game.desc[i]; + for (move_index = 0; move_index <= DESC_STR_LEN; move_index++) { + if (cs->game_desc[move_index] == '\0') + break; + } + cs->game_desc[move_index++] = '\n'; + cs->move_desc_index = move_index; +} +static void manage_labels(ModeInfo *mi) { + Chesscreen *cs = &qs[MI_SCREEN(mi)]; + + if ((cs->stage == DO_MOVE) || (cs->stage == FADE_IN) || + (cs->stage == WAIT_FOR_NEXT_MOVE) || + (cs->stage == WAIT_FOR_NEXT_GAME)) { + if (labels) { + int move_num = (cs->stage == DO_MOVE) ? cs->mc : cs->mc - 1; + texture_font_data *f; + int san_index; + + if (cs->stage != FADE_IN) { + for (san_index = 0; san_index < SAN_STR_LEN; san_index++) { + char c = cs->game.moves[move_num].san[san_index]; + cs->game_desc[cs->move_desc_index + san_index] = c; + if (c == '\0') + break; + } + cs->game_desc[cs->move_desc_index + san_index] = '\0'; + } + if (MI_WIDTH(mi) >= 500 && MI_HEIGHT(mi) >= 375) + f = cs->font1_data; + else if (MI_WIDTH(mi) >= 350 && MI_HEIGHT(mi) >= 260) + f = cs->font2_data; + else + f = cs->font3_data; + glColor3f(0.8, 0.8, 0); + print_texture_label(mi->dpy, f, mi->xgwa.width, mi->xgwa.height, 1, + cs->game_desc); + } + } +} - if((cs->glx_context = init_GL(mi))) - reshape_chess(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); - else - MI_CLEARWINDOW(mi); +/** reshape handler */ +ENTRYPOINT void reshape_chess(ModeInfo *mi, int width, int height) { + GLfloat h = (GLfloat)height / (GLfloat)width; + int y = 0; + + if (width > height * 5) { /* tiny window: show middle */ + height = width * 9 / 16; + y = -height / 2; + h = height / (GLfloat)width; + } - if (!cs->wire) { - glDepthFunc(GL_LEQUAL); - glClearStencil(0); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); + glViewport(0, y, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, 1 / h, 2.0, 30.0); + glMatrixMode(GL_MODELVIEW); +} - make_piece_texture(cs); - make_board_texture(cs); - } - chessmodels_gen_lists( classic, cs->poly_counts); +/** initialization handler */ +ENTRYPOINT void init_chess(ModeInfo *mi) { + Chesscreen *cs; + + MI_INIT(mi, qs); + cs = &qs[MI_SCREEN(mi)]; + + cs->window = MI_WINDOW(mi); + cs->wire = MI_IS_WIREFRAME(mi); + cs->trackball = gltrackball_init(False); + + cs->oldwhite = -1; + + cs->colors[0][0] = 1.0; + cs->colors[0][1] = 0.5; + cs->colors[0][2] = 0.0; + + cs->colors[1][0] = 0.3; + cs->colors[1][1] = 0.3; + cs->colors[1][2] = 0.3; + + cs->stage = CHOSE_GAME; + cs->ticks = 0; + cs->mod = 1.4; + cs->abort = 0; + init_moves(cs); + + /* cs->position[0] = 0.0; */ + /* cs->position[1] = 5.0; */ + /* cs->position[2] = 5.0; */ + /* cs->position[3] = 1.0; */ + + cs->position[0] = 0.0; + cs->position[1] = 24.0; + cs->position[2] = 2.0; + cs->position[3] = 1.0; + + cs->position2[0] = 5.0; + cs->position2[1] = 5.0; + cs->position2[2] = 5.0; + cs->position2[3] = 1.0; + + cs->ground[0] = 0.0; + cs->ground[1] = 1.0; + cs->ground[2] = 0.0; + cs->ground[3] = -0.00001; + + cs->cur_game_idx = -1; + + if ((cs->glx_context = init_GL(mi))) + reshape_chess(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + else + MI_CLEARWINDOW(mi); + + if (!cs->wire) { + glDepthFunc(GL_LEQUAL); + glClearStencil(0); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + make_piece_texture(cs); + make_board_texture(cs); + } + chessmodels_gen_lists(classic, cs->poly_counts); -# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ +#ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ cs->wire = 0; -# endif +#endif - if(!cs->wire) { - setup_lights(cs); - glColorMaterial(GL_FRONT, GL_DIFFUSE); - glShadeModel(smooth ? GL_SMOOTH : GL_FLAT); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_DEPTH_TEST); - } - else - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + if (!cs->wire) { + setup_lights(cs); + glColorMaterial(GL_FRONT, GL_DIFFUSE); + glShadeModel(smooth ? GL_SMOOTH : GL_FLAT); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_DEPTH_TEST); + } else + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + load_fonts(mi); } /** does dirty work drawing scene, moving pieces */ -ENTRYPOINT void draw_chess(ModeInfo *mi) -{ - Chesscreen *cs = &qs[MI_SCREEN(mi)]; - Window w = MI_WINDOW(mi); - Display *disp = MI_DISPLAY(mi); - - if(!cs->glx_context) - return; - - glXMakeCurrent(disp, w, *cs->glx_context); - - /** code for moving a piece */ - if(cs->moving && ++cs->steps == 100) { - cs->moving = cs->count = cs->steps = cs->take = 0; - cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = cs->mpiece; - ++cs->mc; - - if(cs->mc == cs->game.movecount) { - cs->done = 1; - cs->mc = 0; - } - } - - if(++cs->count == 100) { - if(!cs->done) { - cs->mpiece = cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]]; - cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]] = NONE; - - if((cs->tpiece = cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]])) { - cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = NONE; - cs->take = 1; - } - - cs->from[0] = cs->game.moves[cs->mc][0]; - cs->from[1] = cs->game.moves[cs->mc][1]; - cs->to[0] = cs->game.moves[cs->mc][2]; - cs->to[1] = cs->game.moves[cs->mc][3]; - - cs->dz = (cs->to[0] - cs->from[0]) / 100; - cs->dx = (cs->to[1] - cs->from[1]) / 100; - cs->steps = 0; - cs->moving = 1; - } - else if(cs->done == 1) { - int newgame = cs->oldgame; - while(newgame == cs->oldgame) - newgame = random()%GAMES; - - /* mod the mod */ - cs->mod = 0.6 + (random()%20)/10.0; - - /* same old game */ - cs->oldgame = newgame; - cs->game = games[cs->oldgame]; - build_colors(cs); - cs->done = 2; - cs->count = 0; - } - else { - cs->done = 0; - cs->count = 0; +ENTRYPOINT void draw_chess(ModeInfo *mi) { + Chesscreen *cs = &qs[MI_SCREEN(mi)]; + Chessmovestate *movestate; + Window w = MI_WINDOW(mi); + Display *disp = MI_DISPLAY(mi); + int new_game_idx; + + if (!cs->glx_context) + return; + + glXMakeCurrent(disp, w, *cs->glx_context); + + switch (cs->stage) { + case CHOSE_GAME: + new_game_idx = cs->cur_game_idx; + while (new_game_idx == cs->cur_game_idx) + new_game_idx = random() % GAMES_NUMBER; + + /* mod the mod */ + cs->mod = 0.6 + (random() % 20) / 10.0; + + cs->cur_game_idx = new_game_idx; + cs->game = games[cs->cur_game_idx]; + + cs->stage = FADE_IN; + cs->ticks = 1; + cs->mc = 0; + build_colors(cs); + apply_fen(cs); + set_description(cs); + init_moves(cs); + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, + (double)FADE_FACTOR * TICKS_BET_MOVES); + glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, + (double)FADE_FACTOR * TICKS_BET_MOVES); + if (cs->abort) + cs->abort = 0; + break; + case FADE_IN: + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, + (double)FADE_FACTOR * TICKS_BET_MOVES / cs->ticks); + glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, + (double)FADE_FACTOR * TICKS_BET_MOVES / cs->ticks); + if (cs->abort) { + cs->abort = 0; + cs->stage = FADE_OUT; + } else if (cs->ticks++ == FADE_FACTOR * TICKS_BET_MOVES) { + cs->stage = WAIT_FOR_NEXT_MOVE; + } + break; + case FADE_OUT: + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, + (double)FADE_FACTOR * TICKS_BET_MOVES / cs->ticks); + glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, + (double)FADE_FACTOR * TICKS_BET_MOVES / cs->ticks); + if (cs->ticks-- == 0) { + cs->stage = CHOSE_GAME; + } + if (cs->abort) + cs->abort = 0; + break; + case DO_MOVE: + if (cs->abort) { + cs->abort = 0; + cs->ticks = FADE_FACTOR * TICKS_BET_MOVES; + cs->stage = FADE_OUT; + break; + } + /* End of current move(s) */ + if (are_moves_active(cs) && ++cs->steps == NUM_STEPS) { + for (int i = 0; i < CONCURRENT_MOVES; + i++) { /* Update board with moved piece(s) */ + movestate = &(cs->moves[i]); + if (movestate->active) { + cs->board[movestate->to[0]][movestate->to[1]] = + movestate->mpiece; + } + } + /* Reinit stuff for next move */ + cs->ticks = cs->steps = 0; + init_moves(cs); + ++cs->mc; + if (cs->mc == cs->game.movecount) { + cs->ticks = 0; + cs->stage = WAIT_FOR_NEXT_GAME; + cs->mc = 0; + } else { + cs->stage = WAIT_FOR_NEXT_MOVE; + } + } + break; + case WAIT_FOR_NEXT_MOVE: + if (cs->abort) { + cs->abort = 0; + cs->ticks = FADE_FACTOR * TICKS_BET_MOVES; + cs->stage = FADE_OUT; + break; + } + if (cs->ticks++ >= + TICKS_BET_MOVES) { /* Wait before processing next move */ + char *uci = cs->game.moves[cs->mc].uci; + setup_moves(cs, uci); + cs->steps = 0; + cs->ticks = 0; + cs->stage = DO_MOVE; + } + break; + case WAIT_FOR_NEXT_GAME: /* Wait before moving on */ + if (cs->abort) { + cs->abort = 0; + cs->ticks = FADE_FACTOR * TICKS_BET_MOVES; + cs->stage = FADE_OUT; + break; + } + if (cs->ticks++ >= END_FACTOR * TICKS_BET_MOVES) { + cs->ticks = FADE_FACTOR * TICKS_BET_MOVES; + cs->stage = FADE_OUT; + } + break; + default: + break; } - } - - /* set lighting */ - if(cs->done) { - glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, - cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count); - glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, - cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count); glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.14); glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.14); - } - - display(mi, cs); - if(mi->fps_p) do_fps(mi); - glFinish(); - glXSwapBuffers(disp, w); + display(mi, cs); + manage_labels(mi); + if (mi->fps_p) + do_fps(mi); + glFinish(); + glXSwapBuffers(disp, w); } - -ENTRYPOINT void free_chess(ModeInfo *mi) -{ - Chesscreen *cs = &qs[MI_SCREEN(mi)]; - int i; - if (!cs->glx_context) return; - glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *cs->glx_context); - gltrackball_free (cs->trackball); - if (cs->piecetexture) glDeleteTextures (1, &cs->piecetexture); - if (cs->boardtexture) glDeleteTextures (1, &cs->boardtexture); - - /* this is horrible! List numbers are hardcoded! */ - for (i = 1; i <= 20; i++) - if (glIsList(i)) glDeleteLists(i, 1); +ENTRYPOINT void free_chess(ModeInfo *mi) { + Chesscreen *cs = &qs[MI_SCREEN(mi)]; + int i; + if (!cs->glx_context) + return; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *cs->glx_context); + gltrackball_free(cs->trackball); + if (cs->piecetexture) + glDeleteTextures(1, &cs->piecetexture); + if (cs->boardtexture) + glDeleteTextures(1, &cs->boardtexture); + /* this is horrible! List numbers are hardcoded! */ + for (i = 1; i <= 20; i++) + if (glIsList(i)) + glDeleteLists(i, 1); + if (cs->font1_data) + free_texture_font(cs->font1_data); + if (cs->font2_data) + free_texture_font(cs->font2_data); + if (cs->font3_data) + free_texture_font(cs->font3_data); } -XSCREENSAVER_MODULE_2 ("Endgame", endgame, chess) +XSCREENSAVER_MODULE_2("Endgame", endgame, chess) #endif diff --git a/hacks/glx/endgame.man b/hacks/glx/endgame.man index 4b20d460c..02a72dbe0 100644 --- a/hacks/glx/endgame.man +++ b/hacks/glx/endgame.man @@ -1,6 +1,6 @@ .TH XScreenSaver 1 "5-May-2004" .SH NAME -endgame \- endgame chess screensaver +endgame \- re-play classic chess games .SH SYNOPSIS .B endgame [\-\-display \fIhost:display.screen\fP] @@ -39,6 +39,9 @@ Reflect pieces in light board squares. .B \-\-classic Use the original low-polygon piece models. .TP 8 +.B \-\-labels +Display information about the current game and move. +.TP 8 .B \-\-visual \fIvisual\fP\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. @@ -59,8 +62,6 @@ stored in the RESOURCE_MANAGER property. .TP 8 .B XSCREENSAVER_WINDOW The window ID to use with \fI\-\-root\fP. -.SH BUGS -It's not unknown for this and other OpenGL hacks to fail under hardware accelaration (UtahGLX) and take the X server with them. Texture images must be 16x16 or 32x32 or 64x64 etc. .SH SEE ALSO .BR X (1), .BR xscreensaver (1) From 4f86e4ef07a057d270e9a34b334d40f1bef46d43 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 17:47:48 +0200 Subject: [PATCH 14/25] hacks/glx/endgame: add more famous endgames --- hacks/glx/chessgames.h | 1511 +++++++++++++++++++++++++++++++--------- 1 file changed, 1192 insertions(+), 319 deletions(-) diff --git a/hacks/glx/chessgames.h b/hacks/glx/chessgames.h index 28f5c5707..a93015e53 100644 --- a/hacks/glx/chessgames.h +++ b/hacks/glx/chessgames.h @@ -15,329 +15,1202 @@ #ifndef __CHESSGAMES_H__ #define __CHESSGAMES_H__ +#define DESC_STR_LEN 64 /* Length of the game description. */ +#define SAN_STR_LEN 8 /* Length of the move description */ + /** structure for a chess game */ typedef struct { - - /** original board configuration */ - int board[BOARDSIZE][BOARDSIZE]; - - /** total moves */ - int movecount; - - /** - moves in game. this is a slight hack: moves are encoded in - integer pairs (x,y). the first pair, _from_, determines the - piece to move. the second pair, _to_, determines where to move. - - in case _to_ is held by another piece, that piece is taken. - (see drawTakePiece(), draw_chess()) - - in case the move promotes a pawn, we assume a queening. - (see drawMovingPiece()) - - what's lacking? - castling, en passant, under-promotions. - */ - int moves[40][4]; + char desc[DESC_STR_LEN + SAN_STR_LEN + 1]; /* game + move description */ + char fen[80]; /* Original board configuration / FEN format */ + int movecount; /* total moves */ + struct { /* moves in game - as uci and san strings */ + char uci[8]; + char san[8]; + } moves[128]; } ChessGame; -#define GAMES 7 -static ChessGame games[GAMES] = { - - /** - game 1: - - E. N. Somov-Nasimovitsch - White to play and win. - - "Zadachi I Etiudi" - 1928 - */ - { - { - { 0, 0, 0, 0, 0, BKING, 0, 0}, - { BPAWN, 0, BPAWN, 0, BPAWN, 0, 0, 0}, - { 0, 0, BPAWN, 0, BPAWN, 0, 0, KNIGHT}, - { PAWN, 0, ROOK, 0, 0, 0, 0, 0}, - { PAWN, 0, 0, 0, KING, PAWN, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { BPAWN, 0, 0, 0, 0, 0, 0, PAWN}, - { BBISHOP,0, 0, 0, 0, 0, 0, 0}, - }, - - 24, - - { - {3, 2, 6, 2}, - {7, 0, 6, 1}, - {6, 2, 6, 6}, - {0, 5, 0, 4}, - {6, 6, 0, 6}, - {0, 4, 1, 3}, - {2, 7, 1, 5}, - {2, 2, 3, 2}, - {0, 6, 0, 3}, - {1, 3, 2, 2}, - {0, 3, 6, 3}, - {3, 2, 4, 2}, /* pawn to bishop 5 */ - {1, 5, 0, 3}, /* check */ - {2, 2, 3, 2}, - {0, 3, 2, 4}, /* takes pawn */ - {3, 2, 2, 2}, - {2, 4, 0, 3}, - {2, 2, 3, 2}, - {6, 3, 6, 1}, /* rook takes bishop */ - {6, 0, 7, 0}, - {6, 1, 3, 1}, - {3, 2, 2, 3}, - {3, 1, 3, 3}, - {0, 0, 2, 3}, - } - }, - - /** - game 2: - - K. A. L. Kubbel - White to play and win. - - "Chess in the USSR" - 1936 - */ - { - { - { 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, BPAWN}, - { 0, 0, 0, 0, BPAWN, KING, 0, BKING}, - { 0, 0, 0, 0, 0, ROOK, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { 0,BBISHOP, 0, 0, BROOK, 0, PAWN, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0,BISHOP, 0, 0}, - }, - - 10, - - { - {3, 5, 6, 5}, - {5, 1, 7, 3}, - {6, 5, 6, 7}, /* check */ - {7, 3, 3, 7}, - {7, 5, 6, 4}, - {5, 4, 6, 4}, - {5, 6, 4, 6}, /* ! */ - {6, 4, 6, 7}, - {4, 6, 3, 6}, - {0, 0, 2, 7} - } - }, - - /** - game 3: - - J. Hasek - White to play and win. - - "Le Strategie" - 1929 - */ - { - { - { 0, 0, 0, KNIGHT, 0, 0, 0, KNIGHT}, - { 0, KING, BPAWN, BPAWN, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, BKING, 0, 0, 0, 0, 0, 0}, - { 0, PAWN, 0, 0, 0, BPAWN, 0, 0}, - { PAWN, 0, PAWN, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - }, - - 11, - - { - {0, 3, 2, 2}, - {1, 3, 2, 2}, - {0, 7, 2, 6}, - {4, 5, 5, 5}, - {2, 6, 3, 4}, - {5, 5, 6, 5}, - {3, 4, 5, 3}, /* ! */ - {6, 5, 7, 5}, - {5, 3, 6, 1}, - {0, 0, 0, 0}, /* mull it over... */ - {0, 0, 3, 1} - } - }, - - /** - game 4: - - M.B. Newman - White to play and win. - - "Chess Amateur" - 1913 - */ - { - { - { 0, 0, 0, 0, BQUEEN, 0, 0, 0}, - {BKNIGHT, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, PAWN}, - { BKING, 0, BISHOP, 0, KNIGHT, 0, 0, 0}, - { PAWN, 0, 0, 0, KNIGHT, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { KING, 0, 0, 0, 0, 0, 0, 0}, - }, - - 15, - - { - {4, 2, 3, 1}, - {0, 4, 3, 1}, /* queen wins bishop */ - {4, 4, 5, 2}, - {4, 0, 5, 0}, /* king takes pawn */ - {5, 2, 3, 1}, /* knight takes queen, check */ - {1, 0, 3, 1}, /* knight takes knight */ - {3, 7, 2, 7}, /* pawn advances */ - {3, 1, 2, 3}, - {5, 4, 4, 2}, - {2, 3, 4, 2}, - {2, 7, 1, 7}, /* pawn advances */ - {4, 2, 2, 3}, - {1, 7, 0, 7}, - {0, 0, 0, 0}, - {0, 0, 5, 0} - } - }, - - /** - game 5: - - V.A. Korolikov - White to play and win - - First Prize - "Truda" - 1935 - */ - { - { - { 0, 0, BISHOP, 0, 0, 0, 0, 0}, - { BPAWN, ROOK, 0, 0, 0, 0, 0, 0}, - { 0, 0, BPAWN, PAWN, 0, BKING, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, KING, BBISHOP}, - { 0, 0, 0, 0, BPAWN, 0, PAWN, 0}, - { 0, 0, 0, 0, 0, BPAWN, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - }, - - 21, - - { - {2, 3, 1, 3}, /* pawn to q7 */ - {2, 5, 1, 4}, /* cover with king */ - {1, 1, 0, 1}, - {4, 7, 5, 6}, /* bishop takes pawn */ - {0, 1, 0, 0}, /* r - r8 */ - {6, 5, 7, 5}, /* queened */ - {1, 3, 0, 3}, /* white pawn promoted */ - {1, 4, 0, 3}, /* king takes queen */ - {0, 2, 2, 0}, /* discovered check */ - {5, 6, 0, 1}, /* pull back bishop */ - {2, 0, 7, 5}, /* bishop takes queen */ - {0, 3, 1, 2}, - {7, 5, 2, 0}, /* save rook */ - {5, 4, 6, 4}, - {2, 0, 6, 4}, /* bishop takes pawn */ - {1, 2, 1, 1}, /* king moves in */ - {6, 4, 5, 5}, - {1, 1, 0, 0}, - {5, 5, 2, 2}, - {0, 0, 0, 0}, - {0, 0, 0, 0} - } - }, - - /** - game 6: - - T.B. Gorgiev - White to play and win - - First Prize - "64" - 1929 - */ - { - { - { 0, 0, 0, 0, 0, 0, KNIGHT, 0}, - { BKNIGHT, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, BKING, BKNIGHT, 0, 0, 0}, - { KING, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, KNIGHT, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, BISHOP, 0, 0, 0}, - }, - - 13, - - { - {3, 0, 2, 1}, /* king on move */ - {1, 0, 0, 2}, /* check */ - {2, 1, 1, 1}, - {0, 2, 1, 4}, /* knight moves on */ - {7, 4, 5, 6}, /* bishop puts king in check */ - {2, 3, 1, 3}, /* king moves back */ - {0, 6, 2, 5}, /* knight moves in, check */ - {1, 3, 0, 3}, /* king moves back queen */ - {5, 6, 1, 2}, /* bishop - b7 ch!! */ - {2, 4, 1, 2}, /* black knight takes bishop */ - {4, 6, 3, 4}, /* knight to k5 */ - {0, 0, 0, 0}, /* mate */ - {0, 0, 0, 0} - } - }, - - /** - game 7: - - K. A. L. Kubbel - White to play and win - - "Schachmatny Listok" - 1922 - */ - { - { - { 0, KNIGHT, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - { KING, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, BKING, 0, 0, 0, 0}, - { 0, 0, 0, BPAWN, 0, 0, 0, BISHOP}, - { BPAWN, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, PAWN, PAWN, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, 0}, - }, - - 12, - - { - {0, 1, 2, 2}, /* kt-b6 */ - {3, 3, 2, 2}, /* k x kt */ - {4, 7, 2, 5}, /* b-b6 */ - {2, 2, 3, 3}, /* king back to original position */ - {6, 3, 5, 3}, /* p-q3! */ - {5, 0, 6, 0}, /* p-r7 */ - {6, 2, 4, 2}, /* p-b4ch */ - {3, 3, 3, 2}, /* king moves, black cannot capture in passing */ - {2, 0, 1, 1}, /* k-kt7! */ - {6, 0, 7, 0}, /* promo */ - {2, 5, 1, 4}, /* mate */ - {0, 0, 3, 2}, - } - }, +#define GAMES_NUMBER 34 +static ChessGame games[GAMES_NUMBER] = { + {.desc = "A. Anderssen / L. Kieseritzky / 1851\n\"The immortal game\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 45, + .moves = + { + {.uci = "e2e4", .san = "e4"}, {.uci = "e7e5", .san = "e5"}, + {.uci = "f2f4", .san = "f4"}, {.uci = "e5f4", .san = "exf4"}, + {.uci = "f1c4", .san = "Bc4"}, {.uci = "d8h4", .san = "Qh4+"}, + {.uci = "e1f1", .san = "Kf1"}, {.uci = "b7b5", .san = "b5"}, + {.uci = "c4b5", .san = "Bxb5"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "h4h6", .san = "Qh6"}, + {.uci = "d2d3", .san = "d3"}, {.uci = "f6h5", .san = "Nh5"}, + {.uci = "f3h4", .san = "Nh4"}, {.uci = "h6g5", .san = "Qg5"}, + {.uci = "h4f5", .san = "Nf5"}, {.uci = "c7c6", .san = "c6"}, + {.uci = "g2g4", .san = "g4"}, {.uci = "h5f6", .san = "Nf6"}, + {.uci = "h1g1", .san = "Rg1"}, {.uci = "c6b5", .san = "cxb5"}, + {.uci = "h2h4", .san = "h4"}, {.uci = "g5g6", .san = "Qg6"}, + {.uci = "h4h5", .san = "h5"}, {.uci = "g6g5", .san = "Qg5"}, + {.uci = "d1f3", .san = "Qf3"}, {.uci = "f6g8", .san = "Ng8"}, + {.uci = "c1f4", .san = "Bxf4"}, {.uci = "g5f6", .san = "Qf6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "f8c5", .san = "Bc5"}, + {.uci = "c3d5", .san = "Nd5"}, {.uci = "f6b2", .san = "Qxb2"}, + {.uci = "f4d6", .san = "Bd6"}, {.uci = "c5g1", .san = "Bxg1"}, + {.uci = "e4e5", .san = "e5"}, {.uci = "b2a1", .san = "Qxa1+"}, + {.uci = "f1e2", .san = "Ke2"}, {.uci = "b8a6", .san = "Na6"}, + {.uci = "f5g7", .san = "Nxg7+"}, {.uci = "e8d8", .san = "Kd8"}, + {.uci = "f3f6", .san = "Qf6+"}, {.uci = "g8f6", .san = "Nxf6"}, + {.uci = "d6e7", .san = "Be7#"}, + }}, + {.desc = "A. Hoffmann / A. Petrov / 1844\n\"Petrov's immortal\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 40, + .moves = + { + {.uci = "e2e4", .san = "e4"}, {.uci = "e7e5", .san = "e5"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "f1c4", .san = "Bc4"}, {.uci = "f8c5", .san = "Bc5"}, + {.uci = "c2c3", .san = "c3"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "d2d4", .san = "d4"}, {.uci = "e5d4", .san = "exd4"}, + {.uci = "e4e5", .san = "e5"}, {.uci = "f6e4", .san = "Ne4"}, + {.uci = "c4d5", .san = "Bd5"}, {.uci = "e4f2", .san = "Nxf2"}, + {.uci = "e1f2", .san = "Kxf2"}, {.uci = "d4c3", .san = "dxc3+"}, + {.uci = "f2g3", .san = "Kg3"}, {.uci = "c3b2", .san = "cxb2"}, + {.uci = "c1b2", .san = "Bxb2"}, {.uci = "c6e7", .san = "Ne7"}, + {.uci = "f3g5", .san = "Ng5"}, {.uci = "e7d5", .san = "Nxd5"}, + {.uci = "g5f7", .san = "Nxf7"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "f7d8", .san = "Nxd8"}, {.uci = "c5f2", .san = "Bf2+"}, + {.uci = "g3h3", .san = "Kh3"}, {.uci = "d7d6", .san = "d6+"}, + {.uci = "e5e6", .san = "e6"}, {.uci = "d5f4", .san = "Nf4+"}, + {.uci = "h3g4", .san = "Kg4"}, {.uci = "f4e6", .san = "Nxe6"}, + {.uci = "d8e6", .san = "Nxe6"}, {.uci = "c8e6", .san = "Bxe6+"}, + {.uci = "g4g5", .san = "Kg5"}, {.uci = "f8f5", .san = "Rf5+"}, + {.uci = "g5g4", .san = "Kg4"}, {.uci = "h7h5", .san = "h5+"}, + {.uci = "g4h3", .san = "Kh3"}, {.uci = "f5f3", .san = "Rf3#"}, + }}, + {.desc = "A. Anderssen / J. Dufresne / 1852\n\"The evergreen game\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 47, + .moves = + { + {.uci = "e2e4", .san = "e4"}, {.uci = "e7e5", .san = "e5"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "f1c4", .san = "Bc4"}, {.uci = "f8c5", .san = "Bc5"}, + {.uci = "b2b4", .san = "b4"}, {.uci = "c5b4", .san = "Bxb4"}, + {.uci = "c2c3", .san = "c3"}, {.uci = "b4a5", .san = "Ba5"}, + {.uci = "d2d4", .san = "d4"}, {.uci = "e5d4", .san = "exd4"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "d4d3", .san = "d3"}, + {.uci = "d1b3", .san = "Qb3"}, {.uci = "d8f6", .san = "Qf6"}, + {.uci = "e4e5", .san = "e5"}, {.uci = "f6g6", .san = "Qg6"}, + {.uci = "f1e1", .san = "Re1"}, {.uci = "g8e7", .san = "Nge7"}, + {.uci = "c1a3", .san = "Ba3"}, {.uci = "b7b5", .san = "b5"}, + {.uci = "b3b5", .san = "Qxb5"}, {.uci = "a8b8", .san = "Rb8"}, + {.uci = "b5a4", .san = "Qa4"}, {.uci = "a5b6", .san = "Bb6"}, + {.uci = "b1d2", .san = "Nbd2"}, {.uci = "c8b7", .san = "Bb7"}, + {.uci = "d2e4", .san = "Ne4"}, {.uci = "g6f5", .san = "Qf5"}, + {.uci = "c4d3", .san = "Bxd3"}, {.uci = "f5h5", .san = "Qh5"}, + {.uci = "e4f6", .san = "Nf6+"}, {.uci = "g7f6", .san = "gxf6"}, + {.uci = "e5f6", .san = "exf6"}, {.uci = "h8g8", .san = "Rg8"}, + {.uci = "a1d1", .san = "Rad1"}, {.uci = "h5f3", .san = "Qxf3"}, + {.uci = "e1e7", .san = "Rxe7+"}, {.uci = "c6e7", .san = "Nxe7"}, + {.uci = "a4d7", .san = "Qxd7+"}, {.uci = "e8d7", .san = "Kxd7"}, + {.uci = "d3f5", .san = "Bf5+"}, {.uci = "d7e8", .san = "Ke8"}, + {.uci = "f5d7", .san = "Bd7+"}, {.uci = "e8f8", .san = "Kf8"}, + {.uci = "a3e7", .san = "Bxe7#"}, + }}, + {.desc = "P. Morphy / D. Karl / 1858\n\"The opera game\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 33, + .moves = + { + {.uci = "e2e4", .san = "e4"}, {.uci = "e7e5", .san = "e5"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "d7d6", .san = "d6"}, + {.uci = "d2d4", .san = "d4"}, {.uci = "c8g4", .san = "Bg4"}, + {.uci = "d4e5", .san = "dxe5"}, {.uci = "g4f3", .san = "Bxf3"}, + {.uci = "d1f3", .san = "Qxf3"}, {.uci = "d6e5", .san = "dxe5"}, + {.uci = "f1c4", .san = "Bc4"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "f3b3", .san = "Qb3"}, {.uci = "d8e7", .san = "Qe7"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "c7c6", .san = "c6"}, + {.uci = "c1g5", .san = "Bg5"}, {.uci = "b7b5", .san = "b5"}, + {.uci = "c3b5", .san = "Nxb5"}, {.uci = "c6b5", .san = "cxb5"}, + {.uci = "c4b5", .san = "Bxb5+"}, {.uci = "b8d7", .san = "Nbd7"}, + {.uci = "e1c1", .san = "O-O-O"}, {.uci = "a8d8", .san = "Rd8"}, + {.uci = "d1d7", .san = "Rxd7"}, {.uci = "d8d7", .san = "Rxd7"}, + {.uci = "h1d1", .san = "Rd1"}, {.uci = "e7e6", .san = "Qe6"}, + {.uci = "b5d7", .san = "Bxd7+"}, {.uci = "f6d7", .san = "Nxd7"}, + {.uci = "b3b8", .san = "Qb8+"}, {.uci = "d7b8", .san = "Nxb8"}, + {.uci = "d1d8", .san = "Rd8#"}, + }}, + {.desc = "G. Rotlewi / A. Rubinstein / 1907\n\"Rotlewi's immortal game\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 50, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "d7d5", .san = "d5"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "e2e3", .san = "e3"}, {.uci = "c7c5", .san = "c5"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "d4c5", .san = "dxc5"}, {.uci = "f8c5", .san = "Bxc5"}, + {.uci = "a2a3", .san = "a3"}, {.uci = "a7a6", .san = "a6"}, + {.uci = "b2b4", .san = "b4"}, {.uci = "c5d6", .san = "Bd6"}, + {.uci = "c1b2", .san = "Bb2"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "d1d2", .san = "Qd2"}, {.uci = "d8e7", .san = "Qe7"}, + {.uci = "f1d3", .san = "Bd3"}, {.uci = "d5c4", .san = "dxc4"}, + {.uci = "d3c4", .san = "Bxc4"}, {.uci = "b7b5", .san = "b5"}, + {.uci = "c4d3", .san = "Bd3"}, {.uci = "f8d8", .san = "Rd8"}, + {.uci = "d2e2", .san = "Qe2"}, {.uci = "c8b7", .san = "Bb7"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "c6e5", .san = "Ne5"}, + {.uci = "f3e5", .san = "Nxe5"}, {.uci = "d6e5", .san = "Bxe5"}, + {.uci = "f2f4", .san = "f4"}, {.uci = "e5c7", .san = "Bc7"}, + {.uci = "e3e4", .san = "e4"}, {.uci = "a8c8", .san = "Rac8"}, + {.uci = "e4e5", .san = "e5"}, {.uci = "c7b6", .san = "Bb6+"}, + {.uci = "g1h1", .san = "Kh1"}, {.uci = "f6g4", .san = "Ng4"}, + {.uci = "d3e4", .san = "Be4"}, {.uci = "e7h4", .san = "Qh4"}, + {.uci = "g2g3", .san = "g3"}, {.uci = "c8c3", .san = "Rxc3"}, + {.uci = "g3h4", .san = "gxh4"}, {.uci = "d8d2", .san = "Rd2"}, + {.uci = "e2d2", .san = "Qxd2"}, {.uci = "b7e4", .san = "Bxe4+"}, + {.uci = "d2g2", .san = "Qg2"}, {.uci = "c3h3", .san = "Rh3"}, + }}, + {.desc = "E. Bogoljubov / A. Alekhine / 1922.09.21 / Hastings", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 106, + .moves = + { + {.uci = "d2d4", .san = "d4"}, + {.uci = "f7f5", .san = "f5"}, + {.uci = "c2c4", .san = "c4"}, + {.uci = "g8f6", .san = "Nf6"}, + {.uci = "g2g3", .san = "g3"}, + {.uci = "e7e6", .san = "e6"}, + {.uci = "f1g2", .san = "Bg2"}, + {.uci = "f8b4", .san = "Bb4+"}, + {.uci = "c1d2", .san = "Bd2"}, + {.uci = "b4d2", .san = "Bxd2+"}, + {.uci = "b1d2", .san = "Nxd2"}, + {.uci = "b8c6", .san = "Nc6"}, + {.uci = "g1f3", .san = "Ngf3"}, + {.uci = "e8g8", .san = "O-O"}, + {.uci = "e1g1", .san = "O-O"}, + {.uci = "d7d6", .san = "d6"}, + {.uci = "d1b3", .san = "Qb3"}, + {.uci = "g8h8", .san = "Kh8"}, + {.uci = "b3c3", .san = "Qc3"}, + {.uci = "e6e5", .san = "e5"}, + {.uci = "e2e3", .san = "e3"}, + {.uci = "a7a5", .san = "a5"}, + {.uci = "b2b3", .san = "b3"}, + {.uci = "d8e8", .san = "Qe8"}, + {.uci = "a2a3", .san = "a3"}, + {.uci = "e8h5", .san = "Qh5"}, + {.uci = "h2h4", .san = "h4"}, + {.uci = "f6g4", .san = "Ng4"}, + {.uci = "f3g5", .san = "Ng5"}, + {.uci = "c8d7", .san = "Bd7"}, + {.uci = "f2f3", .san = "f3"}, + {.uci = "g4f6", .san = "Nf6"}, + {.uci = "f3f4", .san = "f4"}, + {.uci = "e5e4", .san = "e4"}, + {.uci = "f1d1", .san = "Rfd1"}, + {.uci = "h7h6", .san = "h6"}, + {.uci = "g5h3", .san = "Nh3"}, + {.uci = "d6d5", .san = "d5"}, + {.uci = "d2f1", .san = "Nf1"}, + {.uci = "c6e7", .san = "Ne7"}, + {.uci = "a3a4", .san = "a4"}, + {.uci = "e7c6", .san = "Nc6"}, + {.uci = "d1d2", .san = "Rd2"}, + {.uci = "c6b4", .san = "Nb4"}, + {.uci = "g2h1", .san = "Bh1"}, + {.uci = "h5e8", .san = "Qe8"}, + {.uci = "d2g2", .san = "Rg2"}, + {.uci = "d5c4", .san = "dxc4"}, + {.uci = "b3c4", .san = "bxc4"}, + {.uci = "d7a4", .san = "Bxa4"}, + {.uci = "h3f2", .san = "Nf2"}, + {.uci = "a4d7", .san = "Bd7"}, + {.uci = "f1d2", .san = "Nd2"}, + {.uci = "b7b5", .san = "b5"}, + {.uci = "f2d1", .san = "Nd1"}, + {.uci = "b4d3", .san = "Nd3"}, + {.uci = "a1a5", .san = "Rxa5"}, + {.uci = "b5b4", .san = "b4"}, + {.uci = "a5a8", .san = "Rxa8"}, + {.uci = "b4c3", .san = "bxc3"}, + {.uci = "a8e8", .san = "Rxe8"}, + {.uci = "c3c2", .san = "c2"}, + {.uci = "e8f8", .san = "Rxf8+"}, + {.uci = "h8h7", .san = "Kh7"}, + {.uci = "d1f2", .san = "Nf2"}, + {.uci = "c2c1q", .san = "c1=Q+"}, + {.uci = "d2f1", .san = "Nf1"}, + {.uci = "d3e1", .san = "Ne1"}, + {.uci = "g2h2", .san = "Rh2"}, + {.uci = "c1c4", .san = "Qxc4"}, + {.uci = "f8b8", .san = "Rb8"}, + {.uci = "d7b5", .san = "Bb5"}, + {.uci = "b8b5", .san = "Rxb5"}, + {.uci = "c4b5", .san = "Qxb5"}, + {.uci = "g3g4", .san = "g4"}, + {.uci = "e1f3", .san = "Nf3+"}, + {.uci = "h1f3", .san = "Bxf3"}, + {.uci = "e4f3", .san = "exf3"}, + {.uci = "g4f5", .san = "gxf5"}, + {.uci = "b5e2", .san = "Qe2"}, + {.uci = "d4d5", .san = "d5"}, + {.uci = "h7g8", .san = "Kg8"}, + {.uci = "h4h5", .san = "h5"}, + {.uci = "g8h7", .san = "Kh7"}, + {.uci = "e3e4", .san = "e4"}, + {.uci = "f6e4", .san = "Nxe4"}, + {.uci = "f2e4", .san = "Nxe4"}, + {.uci = "e2e4", .san = "Qxe4"}, + {.uci = "d5d6", .san = "d6"}, + {.uci = "c7d6", .san = "cxd6"}, + {.uci = "f5f6", .san = "f6"}, + {.uci = "g7f6", .san = "gxf6"}, + {.uci = "h2d2", .san = "Rd2"}, + {.uci = "e4e2", .san = "Qe2"}, + {.uci = "d2e2", .san = "Rxe2"}, + {.uci = "f3e2", .san = "fxe2"}, + {.uci = "g1f2", .san = "Kf2"}, + {.uci = "e2f1q", .san = "exf1=Q+"}, + {.uci = "f2f1", .san = "Kxf1"}, + {.uci = "h7g7", .san = "Kg7"}, + {.uci = "f1e2", .san = "Ke2"}, + {.uci = "g7f7", .san = "Kf7"}, + {.uci = "e2e3", .san = "Ke3"}, + {.uci = "f7e6", .san = "Ke6"}, + {.uci = "e3e4", .san = "Ke4"}, + {.uci = "d6d5", .san = "d5+"}, + }}, + {.desc = "Glucksberg / M. Najdorf / 1929\n\"The Polish immortal\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 44, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "f7f5", .san = "f5"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "d7d5", .san = "d5"}, + {.uci = "e2e3", .san = "e3"}, {.uci = "c7c6", .san = "c6"}, + {.uci = "f1d3", .san = "Bd3"}, {.uci = "f8d6", .san = "Bd6"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "c3e2", .san = "Ne2"}, {.uci = "b8d7", .san = "Nbd7"}, + {.uci = "f3g5", .san = "Ng5"}, {.uci = "d6h2", .san = "Bxh2+"}, + {.uci = "g1h1", .san = "Kh1"}, {.uci = "f6g4", .san = "Ng4"}, + {.uci = "f2f4", .san = "f4"}, {.uci = "d8e8", .san = "Qe8"}, + {.uci = "g2g3", .san = "g3"}, {.uci = "e8h5", .san = "Qh5"}, + {.uci = "h1g2", .san = "Kg2"}, {.uci = "h2g1", .san = "Bg1"}, + {.uci = "e2g1", .san = "Nxg1"}, {.uci = "h5h2", .san = "Qh2+"}, + {.uci = "g2f3", .san = "Kf3"}, {.uci = "e6e5", .san = "e5"}, + {.uci = "d4e5", .san = "dxe5"}, {.uci = "d7e5", .san = "Ndxe5+"}, + {.uci = "f4e5", .san = "fxe5"}, {.uci = "g4e5", .san = "Nxe5+"}, + {.uci = "f3f4", .san = "Kf4"}, {.uci = "e5g6", .san = "Ng6+"}, + {.uci = "f4f3", .san = "Kf3"}, {.uci = "f5f4", .san = "f4"}, + {.uci = "e3f4", .san = "exf4"}, {.uci = "c8g4", .san = "Bg4+"}, + {.uci = "f3g4", .san = "Kxg4"}, {.uci = "g6e5", .san = "Ne5+"}, + {.uci = "f4e5", .san = "fxe5"}, {.uci = "h7h5", .san = "h5#"}, + }}, + {.desc = "D. Byrne / R. J. Fischer / 1956\n\"The game of the century\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 82, + .moves = + { + {.uci = "g1f3", .san = "Nf3"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "g7g6", .san = "g6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "f8g7", .san = "Bg7"}, + {.uci = "d2d4", .san = "d4"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "c1f4", .san = "Bf4"}, {.uci = "d7d5", .san = "d5"}, + {.uci = "d1b3", .san = "Qb3"}, {.uci = "d5c4", .san = "dxc4"}, + {.uci = "b3c4", .san = "Qxc4"}, {.uci = "c7c6", .san = "c6"}, + {.uci = "e2e4", .san = "e4"}, {.uci = "b8d7", .san = "Nbd7"}, + {.uci = "a1d1", .san = "Rd1"}, {.uci = "d7b6", .san = "Nb6"}, + {.uci = "c4c5", .san = "Qc5"}, {.uci = "c8g4", .san = "Bg4"}, + {.uci = "f4g5", .san = "Bg5"}, {.uci = "b6a4", .san = "Na4"}, + {.uci = "c5a3", .san = "Qa3"}, {.uci = "a4c3", .san = "Nxc3"}, + {.uci = "b2c3", .san = "bxc3"}, {.uci = "f6e4", .san = "Nxe4"}, + {.uci = "g5e7", .san = "Bxe7"}, {.uci = "d8b6", .san = "Qb6"}, + {.uci = "f1c4", .san = "Bc4"}, {.uci = "e4c3", .san = "Nxc3"}, + {.uci = "e7c5", .san = "Bc5"}, {.uci = "f8e8", .san = "Rfe8+"}, + {.uci = "e1f1", .san = "Kf1"}, {.uci = "g4e6", .san = "Be6"}, + {.uci = "c5b6", .san = "Bxb6"}, {.uci = "e6c4", .san = "Bxc4+"}, + {.uci = "f1g1", .san = "Kg1"}, {.uci = "c3e2", .san = "Ne2+"}, + {.uci = "g1f1", .san = "Kf1"}, {.uci = "e2d4", .san = "Nxd4+"}, + {.uci = "f1g1", .san = "Kg1"}, {.uci = "d4e2", .san = "Ne2+"}, + {.uci = "g1f1", .san = "Kf1"}, {.uci = "e2c3", .san = "Nc3+"}, + {.uci = "f1g1", .san = "Kg1"}, {.uci = "a7b6", .san = "axb6"}, + {.uci = "a3b4", .san = "Qb4"}, {.uci = "a8a4", .san = "Ra4"}, + {.uci = "b4b6", .san = "Qxb6"}, {.uci = "c3d1", .san = "Nxd1"}, + {.uci = "h2h3", .san = "h3"}, {.uci = "a4a2", .san = "Rxa2"}, + {.uci = "g1h2", .san = "Kh2"}, {.uci = "d1f2", .san = "Nxf2"}, + {.uci = "h1e1", .san = "Re1"}, {.uci = "e8e1", .san = "Rxe1"}, + {.uci = "b6d8", .san = "Qd8+"}, {.uci = "g7f8", .san = "Bf8"}, + {.uci = "f3e1", .san = "Nxe1"}, {.uci = "c4d5", .san = "Bd5"}, + {.uci = "e1f3", .san = "Nf3"}, {.uci = "f2e4", .san = "Ne4"}, + {.uci = "d8b8", .san = "Qb8"}, {.uci = "b7b5", .san = "b5"}, + {.uci = "h3h4", .san = "h4"}, {.uci = "h7h5", .san = "h5"}, + {.uci = "f3e5", .san = "Ne5"}, {.uci = "g8g7", .san = "Kg7"}, + {.uci = "h2g1", .san = "Kg1"}, {.uci = "f8c5", .san = "Bc5+"}, + {.uci = "g1f1", .san = "Kf1"}, {.uci = "e4g3", .san = "Ng3+"}, + {.uci = "f1e1", .san = "Ke1"}, {.uci = "c5b4", .san = "Bb4+"}, + {.uci = "e1d1", .san = "Kd1"}, {.uci = "d5b3", .san = "Bb3+"}, + {.uci = "d1c1", .san = "Kc1"}, {.uci = "g3e2", .san = "Ne2+"}, + {.uci = "c1b1", .san = "Kb1"}, {.uci = "e2c3", .san = "Nc3+"}, + {.uci = "b1c1", .san = "Kc1"}, {.uci = "a2c2", .san = "Rc2#"}, + }}, + {.desc = "G. Kasparov / V. Topalov / 1999\n\"Kasparov's immortal\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 87, + .moves = + { + {.uci = "e2e4", .san = "e4"}, {.uci = "d7d6", .san = "d6"}, + {.uci = "d2d4", .san = "d4"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "g7g6", .san = "g6"}, + {.uci = "c1e3", .san = "Be3"}, {.uci = "f8g7", .san = "Bg7"}, + {.uci = "d1d2", .san = "Qd2"}, {.uci = "c7c6", .san = "c6"}, + {.uci = "f2f3", .san = "f3"}, {.uci = "b7b5", .san = "b5"}, + {.uci = "g1e2", .san = "Nge2"}, {.uci = "b8d7", .san = "Nbd7"}, + {.uci = "e3h6", .san = "Bh6"}, {.uci = "g7h6", .san = "Bxh6"}, + {.uci = "d2h6", .san = "Qxh6"}, {.uci = "c8b7", .san = "Bb7"}, + {.uci = "a2a3", .san = "a3"}, {.uci = "e7e5", .san = "e5"}, + {.uci = "e1c1", .san = "O-O-O"}, {.uci = "d8e7", .san = "Qe7"}, + {.uci = "c1b1", .san = "Kb1"}, {.uci = "a7a6", .san = "a6"}, + {.uci = "e2c1", .san = "Nc1"}, {.uci = "e8c8", .san = "O-O-O"}, + {.uci = "c1b3", .san = "Nb3"}, {.uci = "e5d4", .san = "exd4"}, + {.uci = "d1d4", .san = "Rxd4"}, {.uci = "c6c5", .san = "c5"}, + {.uci = "d4d1", .san = "Rd1"}, {.uci = "d7b6", .san = "Nb6"}, + {.uci = "g2g3", .san = "g3"}, {.uci = "c8b8", .san = "Kb8"}, + {.uci = "b3a5", .san = "Na5"}, {.uci = "b7a8", .san = "Ba8"}, + {.uci = "f1h3", .san = "Bh3"}, {.uci = "d6d5", .san = "d5"}, + {.uci = "h6f4", .san = "Qf4+"}, {.uci = "b8a7", .san = "Ka7"}, + {.uci = "h1e1", .san = "Rhe1"}, {.uci = "d5d4", .san = "d4"}, + {.uci = "c3d5", .san = "Nd5"}, {.uci = "b6d5", .san = "Nbxd5"}, + {.uci = "e4d5", .san = "exd5"}, {.uci = "e7d6", .san = "Qd6"}, + {.uci = "d1d4", .san = "Rxd4"}, {.uci = "c5d4", .san = "cxd4"}, + {.uci = "e1e7", .san = "Re7+"}, {.uci = "a7b6", .san = "Kb6"}, + {.uci = "f4d4", .san = "Qxd4+"}, {.uci = "b6a5", .san = "Kxa5"}, + {.uci = "b2b4", .san = "b4+"}, {.uci = "a5a4", .san = "Ka4"}, + {.uci = "d4c3", .san = "Qc3"}, {.uci = "d6d5", .san = "Qxd5"}, + {.uci = "e7a7", .san = "Ra7"}, {.uci = "a8b7", .san = "Bb7"}, + {.uci = "a7b7", .san = "Rxb7"}, {.uci = "d5c4", .san = "Qc4"}, + {.uci = "c3f6", .san = "Qxf6"}, {.uci = "a4a3", .san = "Kxa3"}, + {.uci = "f6a6", .san = "Qxa6+"}, {.uci = "a3b4", .san = "Kxb4"}, + {.uci = "c2c3", .san = "c3+"}, {.uci = "b4c3", .san = "Kxc3"}, + {.uci = "a6a1", .san = "Qa1+"}, {.uci = "c3d2", .san = "Kd2"}, + {.uci = "a1b2", .san = "Qb2+"}, {.uci = "d2d1", .san = "Kd1"}, + {.uci = "h3f1", .san = "Bf1"}, {.uci = "d8d2", .san = "Rd2"}, + {.uci = "b7d7", .san = "Rd7"}, {.uci = "d2d7", .san = "Rxd7"}, + {.uci = "f1c4", .san = "Bxc4"}, {.uci = "b5c4", .san = "bxc4"}, + {.uci = "b2h8", .san = "Qxh8"}, {.uci = "d7d3", .san = "Rd3"}, + {.uci = "h8a8", .san = "Qa8"}, {.uci = "c4c3", .san = "c3"}, + {.uci = "a8a4", .san = "Qa4+"}, {.uci = "d1e1", .san = "Ke1"}, + {.uci = "f3f4", .san = "f4"}, {.uci = "f7f5", .san = "f5"}, + {.uci = "b1c1", .san = "Kc1"}, {.uci = "d3d2", .san = "Rd2"}, + {.uci = "a4a7", .san = "Qa7"}, + }}, + {.desc = "W. Yi / L. B. Bruzon / 2015.07.03\n6th Hainan Danzhou", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 71, + .moves = + { + {.uci = "e2e4", .san = "e4"}, {.uci = "c7c5", .san = "c5"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "a7a6", .san = "a6"}, + {.uci = "f1e2", .san = "Be2"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "d2d4", .san = "d4"}, {.uci = "c5d4", .san = "cxd4"}, + {.uci = "f3d4", .san = "Nxd4"}, {.uci = "d8c7", .san = "Qc7"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "c1e3", .san = "Be3"}, {.uci = "f8e7", .san = "Be7"}, + {.uci = "f2f4", .san = "f4"}, {.uci = "d7d6", .san = "d6"}, + {.uci = "g1h1", .san = "Kh1"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "d1e1", .san = "Qe1"}, {.uci = "c6d4", .san = "Nxd4"}, + {.uci = "e3d4", .san = "Bxd4"}, {.uci = "b7b5", .san = "b5"}, + {.uci = "e1g3", .san = "Qg3"}, {.uci = "c8b7", .san = "Bb7"}, + {.uci = "a2a3", .san = "a3"}, {.uci = "a8d8", .san = "Rad8"}, + {.uci = "a1e1", .san = "Rae1"}, {.uci = "d8d7", .san = "Rd7"}, + {.uci = "e2d3", .san = "Bd3"}, {.uci = "c7d8", .san = "Qd8"}, + {.uci = "g3h3", .san = "Qh3"}, {.uci = "g7g6", .san = "g6"}, + {.uci = "f4f5", .san = "f5"}, {.uci = "e6e5", .san = "e5"}, + {.uci = "d4e3", .san = "Be3"}, {.uci = "f8e8", .san = "Re8"}, + {.uci = "f5g6", .san = "fxg6"}, {.uci = "h7g6", .san = "hxg6"}, + {.uci = "c3d5", .san = "Nd5"}, {.uci = "f6d5", .san = "Nxd5"}, + {.uci = "f1f7", .san = "Rxf7"}, {.uci = "g8f7", .san = "Kxf7"}, + {.uci = "h3h7", .san = "Qh7+"}, {.uci = "f7e6", .san = "Ke6"}, + {.uci = "e4d5", .san = "exd5+"}, {.uci = "e6d5", .san = "Kxd5"}, + {.uci = "d3e4", .san = "Be4+"}, {.uci = "d5e4", .san = "Kxe4"}, + {.uci = "h7f7", .san = "Qf7"}, {.uci = "e7f6", .san = "Bf6"}, + {.uci = "e3d2", .san = "Bd2+"}, {.uci = "e4d4", .san = "Kd4"}, + {.uci = "d2e3", .san = "Be3+"}, {.uci = "d4e4", .san = "Ke4"}, + {.uci = "f7b3", .san = "Qb3"}, {.uci = "e4f5", .san = "Kf5"}, + {.uci = "e1f1", .san = "Rf1+"}, {.uci = "f5g4", .san = "Kg4"}, + {.uci = "b3d3", .san = "Qd3"}, {.uci = "b7g2", .san = "Bxg2+"}, + {.uci = "h1g2", .san = "Kxg2"}, {.uci = "d8a8", .san = "Qa8+"}, + {.uci = "g2g1", .san = "Kg1"}, {.uci = "f6g5", .san = "Bg5"}, + {.uci = "d3e2", .san = "Qe2+"}, {.uci = "g4h4", .san = "Kh4"}, + {.uci = "e3f2", .san = "Bf2+"}, {.uci = "h4h3", .san = "Kh3"}, + {.uci = "f2e1", .san = "Be1"}, + }}, + {.desc = "L. Polugaevsky / R. G. Nezhmetdinov / 1958 / Sochi", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 66, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "d7d6", .san = "d6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "e7e5", .san = "e5"}, + {.uci = "e2e4", .san = "e4"}, {.uci = "e5d4", .san = "exd4"}, + {.uci = "d1d4", .san = "Qxd4"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "d4d2", .san = "Qd2"}, {.uci = "g7g6", .san = "g6"}, + {.uci = "b2b3", .san = "b3"}, {.uci = "f8g7", .san = "Bg7"}, + {.uci = "c1b2", .san = "Bb2"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "f1d3", .san = "Bd3"}, {.uci = "f6g4", .san = "Ng4"}, + {.uci = "g1e2", .san = "Nge2"}, {.uci = "d8h4", .san = "Qh4"}, + {.uci = "e2g3", .san = "Ng3"}, {.uci = "g4e5", .san = "Nge5"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "f7f5", .san = "f5"}, + {.uci = "f2f3", .san = "f3"}, {.uci = "g7h6", .san = "Bh6"}, + {.uci = "d2d1", .san = "Qd1"}, {.uci = "f5f4", .san = "f4"}, + {.uci = "g3e2", .san = "Nge2"}, {.uci = "g6g5", .san = "g5"}, + {.uci = "c3d5", .san = "Nd5"}, {.uci = "g5g4", .san = "g4"}, + {.uci = "g2g3", .san = "g3"}, {.uci = "f4g3", .san = "fxg3"}, + {.uci = "h2g3", .san = "hxg3"}, {.uci = "h4h3", .san = "Qh3"}, + {.uci = "f3f4", .san = "f4"}, {.uci = "c8e6", .san = "Be6"}, + {.uci = "d3c2", .san = "Bc2"}, {.uci = "f8f7", .san = "Rf7"}, + {.uci = "g1f2", .san = "Kf2"}, {.uci = "h3h2", .san = "Qh2+"}, + {.uci = "f2e3", .san = "Ke3"}, {.uci = "e6d5", .san = "Bxd5"}, + {.uci = "c4d5", .san = "cxd5"}, {.uci = "c6b4", .san = "Nb4"}, + {.uci = "f1h1", .san = "Rh1"}, {.uci = "f7f4", .san = "Rxf4"}, + {.uci = "h1h2", .san = "Rxh2"}, {.uci = "f4f3", .san = "Rf3+"}, + {.uci = "e3d4", .san = "Kd4"}, {.uci = "h6g7", .san = "Bg7"}, + {.uci = "a2a4", .san = "a4"}, {.uci = "c7c5", .san = "c5+"}, + {.uci = "d5c6", .san = "dxc6"}, /* e.p. */ + {.uci = "b7c6", .san = "bxc6"}, {.uci = "c2d3", .san = "Bd3"}, + {.uci = "e5d3", .san = "Nexd3+"}, {.uci = "d4c4", .san = "Kc4"}, + {.uci = "d6d5", .san = "d5+"}, {.uci = "e4d5", .san = "exd5"}, + {.uci = "c6d5", .san = "cxd5+"}, {.uci = "c4b5", .san = "Kb5"}, + {.uci = "a8b8", .san = "Rb8+"}, {.uci = "b5a5", .san = "Ka5"}, + {.uci = "b4c6", .san = "Nc6+"}, + }}, + {.desc = "M. Botvinnik / J. R. Capablanca / 1938.11.22 / Rotterdam", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 81, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "f8b4", .san = "Bb4"}, + {.uci = "e2e3", .san = "e3"}, {.uci = "d7d5", .san = "d5"}, + {.uci = "a2a3", .san = "a3"}, {.uci = "b4c3", .san = "Bxc3+"}, + {.uci = "b2c3", .san = "bxc3"}, {.uci = "c7c5", .san = "c5"}, + {.uci = "c4d5", .san = "cxd5"}, {.uci = "e6d5", .san = "exd5"}, + {.uci = "f1d3", .san = "Bd3"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "g1e2", .san = "Ne2"}, {.uci = "b7b6", .san = "b6"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "c8a6", .san = "Ba6"}, + {.uci = "d3a6", .san = "Bxa6"}, {.uci = "b8a6", .san = "Nxa6"}, + {.uci = "c1b2", .san = "Bb2"}, {.uci = "d8d7", .san = "Qd7"}, + {.uci = "a3a4", .san = "a4"}, {.uci = "f8e8", .san = "Rfe8"}, + {.uci = "d1d3", .san = "Qd3"}, {.uci = "c5c4", .san = "c4"}, + {.uci = "d3c2", .san = "Qc2"}, {.uci = "a6b8", .san = "Nb8"}, + {.uci = "a1e1", .san = "Rae1"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "e2g3", .san = "Ng3"}, {.uci = "c6a5", .san = "Na5"}, + {.uci = "f2f3", .san = "f3"}, {.uci = "a5b3", .san = "Nb3"}, + {.uci = "e3e4", .san = "e4"}, {.uci = "d7a4", .san = "Qxa4"}, + {.uci = "e4e5", .san = "e5"}, {.uci = "f6d7", .san = "Nd7"}, + {.uci = "c2f2", .san = "Qf2"}, {.uci = "g7g6", .san = "g6"}, + {.uci = "f3f4", .san = "f4"}, {.uci = "f7f5", .san = "f5"}, + {.uci = "e5f6", .san = "exf6"}, /* e.p. */ + {.uci = "d7f6", .san = "Nxf6"}, {.uci = "f4f5", .san = "f5"}, + {.uci = "e8e1", .san = "Rxe1"}, {.uci = "f1e1", .san = "Rxe1"}, + {.uci = "a8e8", .san = "Re8"}, {.uci = "e1e6", .san = "Re6"}, + {.uci = "e8e6", .san = "Rxe6"}, {.uci = "f5e6", .san = "fxe6"}, + {.uci = "g8g7", .san = "Kg7"}, {.uci = "f2f4", .san = "Qf4"}, + {.uci = "a4e8", .san = "Qe8"}, {.uci = "f4e5", .san = "Qe5"}, + {.uci = "e8e7", .san = "Qe7"}, {.uci = "b2a3", .san = "Ba3"}, + {.uci = "e7a3", .san = "Qxa3"}, {.uci = "g3h5", .san = "Nh5+"}, + {.uci = "g6h5", .san = "gxh5"}, {.uci = "e5g5", .san = "Qg5+"}, + {.uci = "g7f8", .san = "Kf8"}, {.uci = "g5f6", .san = "Qxf6+"}, + {.uci = "f8g8", .san = "Kg8"}, {.uci = "e6e7", .san = "e7"}, + {.uci = "a3c1", .san = "Qc1+"}, {.uci = "g1f2", .san = "Kf2"}, + {.uci = "c1c2", .san = "Qc2+"}, {.uci = "f2g3", .san = "Kg3"}, + {.uci = "c2d3", .san = "Qd3+"}, {.uci = "g3h4", .san = "Kh4"}, + {.uci = "d3e4", .san = "Qe4+"}, {.uci = "h4h5", .san = "Kxh5"}, + {.uci = "e4e2", .san = "Qe2+"}, {.uci = "h5h4", .san = "Kh4"}, + {.uci = "e2e4", .san = "Qe4+"}, {.uci = "g2g4", .san = "g4"}, + {.uci = "e4e1", .san = "Qe1+"}, {.uci = "h4h5", .san = "Kh5"}, + }}, + {.desc = "V. Bagirov / E. Gufeld / 1973\n\"Mona Lisa\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 64, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "g7g6", .san = "g6"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "f8g7", .san = "Bg7"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "d7d6", .san = "d6"}, + {.uci = "e2e4", .san = "e4"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "f2f3", .san = "f3"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "c1e3", .san = "Be3"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "g1e2", .san = "Nge2"}, {.uci = "a8b8", .san = "Rb8"}, + {.uci = "d1d2", .san = "Qd2"}, {.uci = "a7a6", .san = "a6"}, + {.uci = "e3h6", .san = "Bh6"}, {.uci = "b7b5", .san = "b5"}, + {.uci = "h2h4", .san = "h4"}, {.uci = "e7e5", .san = "e5"}, + {.uci = "h6g7", .san = "Bxg7"}, {.uci = "g8g7", .san = "Kxg7"}, + {.uci = "h4h5", .san = "h5"}, {.uci = "g7h8", .san = "Kh8"}, + {.uci = "c3d5", .san = "Nd5"}, {.uci = "b5c4", .san = "bxc4"}, + {.uci = "h5g6", .san = "hxg6"}, {.uci = "f7g6", .san = "fxg6"}, + {.uci = "d2h6", .san = "Qh6"}, {.uci = "f6h5", .san = "Nh5"}, + {.uci = "g2g4", .san = "g4"}, {.uci = "b8b2", .san = "Rxb2"}, + {.uci = "g4h5", .san = "gxh5"}, {.uci = "g6g5", .san = "g5"}, + {.uci = "h1g1", .san = "Rg1"}, {.uci = "g5g4", .san = "g4"}, + {.uci = "e1c1", .san = "O-O-O"}, {.uci = "b2a2", .san = "Rxa2"}, + {.uci = "e2f4", .san = "Nef4"}, {.uci = "e5f4", .san = "exf4"}, + {.uci = "d5f4", .san = "Nxf4"}, {.uci = "f8f4", .san = "Rxf4"}, + {.uci = "h6f4", .san = "Qxf4"}, {.uci = "c4c3", .san = "c3"}, + {.uci = "f1c4", .san = "Bc4"}, {.uci = "a2a3", .san = "Ra3"}, + {.uci = "f3g4", .san = "fxg4"}, {.uci = "c6b4", .san = "Nb4"}, + {.uci = "c1b1", .san = "Kb1"}, {.uci = "c8e6", .san = "Be6"}, + {.uci = "c4e6", .san = "Bxe6"}, {.uci = "b4d3", .san = "Nd3"}, + {.uci = "f4f7", .san = "Qf7"}, {.uci = "d8b8", .san = "Qb8+"}, + {.uci = "e6b3", .san = "Bb3"}, {.uci = "a3b3", .san = "Rxb3+"}, + {.uci = "b1c2", .san = "Kc2"}, {.uci = "d3b4", .san = "Nb4+"}, + {.uci = "c2b3", .san = "Kxb3"}, {.uci = "b4d5", .san = "Nd5+"}, + {.uci = "b3c2", .san = "Kc2"}, {.uci = "b8b2", .san = "Qb2+"}, + {.uci = "c2d3", .san = "Kd3"}, {.uci = "b2b5", .san = "Qb5+"}, + }}, + {.desc = "A. Beliavsky / J. Nunn / 1985", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 54, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "g7g6", .san = "g6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "f8g7", .san = "Bg7"}, + {.uci = "e2e4", .san = "e4"}, {.uci = "d7d6", .san = "d6"}, + {.uci = "f2f3", .san = "f3"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "c1e3", .san = "Be3"}, {.uci = "b8d7", .san = "Nbd7"}, + {.uci = "d1d2", .san = "Qd2"}, {.uci = "c7c5", .san = "c5"}, + {.uci = "d4d5", .san = "d5"}, {.uci = "d7e5", .san = "Ne5"}, + {.uci = "h2h3", .san = "h3"}, {.uci = "f6h5", .san = "Nh5"}, + {.uci = "e3f2", .san = "Bf2"}, {.uci = "f7f5", .san = "f5"}, + {.uci = "e4f5", .san = "exf5"}, {.uci = "f8f5", .san = "Rxf5"}, + {.uci = "g2g4", .san = "g4"}, {.uci = "f5f3", .san = "Rxf3"}, + {.uci = "g4h5", .san = "gxh5"}, {.uci = "d8f8", .san = "Qf8"}, + {.uci = "c3e4", .san = "Ne4"}, {.uci = "g7h6", .san = "Bh6"}, + {.uci = "d2c2", .san = "Qc2"}, {.uci = "f8f4", .san = "Qf4"}, + {.uci = "g1e2", .san = "Ne2"}, {.uci = "f3f2", .san = "Rxf2"}, + {.uci = "e4f2", .san = "Nxf2"}, {.uci = "e5f3", .san = "Nf3+"}, + {.uci = "e1d1", .san = "Kd1"}, {.uci = "f4h4", .san = "Qh4"}, + {.uci = "f2d3", .san = "Nd3"}, {.uci = "c8f5", .san = "Bf5"}, + {.uci = "e2c1", .san = "Nec1"}, {.uci = "f3d2", .san = "Nd2"}, + {.uci = "h5g6", .san = "hxg6"}, {.uci = "h7g6", .san = "hxg6"}, + {.uci = "f1g2", .san = "Bg2"}, {.uci = "d2c4", .san = "Nxc4"}, + {.uci = "c2f2", .san = "Qf2"}, {.uci = "c4e3", .san = "Ne3+"}, + {.uci = "d1e2", .san = "Ke2"}, {.uci = "h4c4", .san = "Qc4"}, + {.uci = "g2f3", .san = "Bf3"}, {.uci = "a8f8", .san = "Rf8"}, + {.uci = "h1g1", .san = "Rg1"}, {.uci = "e3c2", .san = "Nc2"}, + {.uci = "e2d1", .san = "Kd1"}, {.uci = "f5d3", .san = "Bxd3"}, + }}, + {.desc = "A. Shirov / J. Polgar / 1994 / Buenos Aires", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 58, + .moves = + { + {.uci = "e2e4", .san = "e4"}, {.uci = "c7c5", .san = "c5"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "d2d4", .san = "d4"}, {.uci = "c5d4", .san = "cxd4"}, + {.uci = "f3d4", .san = "Nxd4"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "d7d6", .san = "d6"}, + {.uci = "g2g4", .san = "g4"}, {.uci = "a7a6", .san = "a6"}, + {.uci = "c1e3", .san = "Be3"}, {.uci = "g8e7", .san = "Nge7"}, + {.uci = "d4b3", .san = "Nb3"}, {.uci = "b7b5", .san = "b5"}, + {.uci = "f2f4", .san = "f4"}, {.uci = "c8b7", .san = "Bb7"}, + {.uci = "d1f3", .san = "Qf3"}, {.uci = "g7g5", .san = "g5"}, + {.uci = "f4g5", .san = "fxg5"}, {.uci = "c6e5", .san = "Ne5"}, + {.uci = "f3g2", .san = "Qg2"}, {.uci = "b5b4", .san = "b4"}, + {.uci = "c3e2", .san = "Ne2"}, {.uci = "h7h5", .san = "h5"}, + {.uci = "g4h5", .san = "gxh5"}, {.uci = "e7f5", .san = "Nf5"}, + {.uci = "e3f2", .san = "Bf2"}, {.uci = "d8g5", .san = "Qxg5"}, + {.uci = "b3a5", .san = "Na5"}, {.uci = "f5e3", .san = "Ne3"}, + {.uci = "g2g3", .san = "Qg3"}, {.uci = "g5g3", .san = "Qxg3"}, + {.uci = "e2g3", .san = "Nxg3"}, {.uci = "e3c2", .san = "Nxc2+"}, + {.uci = "e1d1", .san = "Kd1"}, {.uci = "c2a1", .san = "Nxa1"}, + {.uci = "a5b7", .san = "Nxb7"}, {.uci = "b4b3", .san = "b3"}, + {.uci = "a2b3", .san = "axb3"}, {.uci = "a1b3", .san = "Nxb3"}, + {.uci = "d1c2", .san = "Kc2"}, {.uci = "b3c5", .san = "Nc5"}, + {.uci = "b7c5", .san = "Nxc5"}, {.uci = "d6c5", .san = "dxc5"}, + {.uci = "f2e1", .san = "Be1"}, {.uci = "e5f3", .san = "Nf3"}, + {.uci = "e1c3", .san = "Bc3"}, {.uci = "f3d4", .san = "Nd4+"}, + {.uci = "c2d3", .san = "Kd3"}, {.uci = "f8d6", .san = "Bd6"}, + {.uci = "f1g2", .san = "Bg2"}, {.uci = "d6e5", .san = "Be5"}, + {.uci = "d3c4", .san = "Kc4"}, {.uci = "e8e7", .san = "Ke7"}, + {.uci = "h1a1", .san = "Ra1"}, {.uci = "d4c6", .san = "Nc6"}, + }}, + {.desc = "V. Ivanchuk / A. Yusupov / 1991\n\"Ivanchuck's immortal\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 78, + .moves = + { + {.uci = "c2c4", .san = "c4"}, {.uci = "e7e5", .san = "e5"}, + {.uci = "g2g3", .san = "g3"}, {.uci = "d7d6", .san = "d6"}, + {.uci = "f1g2", .san = "Bg2"}, {.uci = "g7g6", .san = "g6"}, + {.uci = "d2d4", .san = "d4"}, {.uci = "b8d7", .san = "Nd7"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "f8g7", .san = "Bg7"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "g8f6", .san = "Ngf6"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "d1c2", .san = "Qc2"}, {.uci = "f8e8", .san = "Re8"}, + {.uci = "f1d1", .san = "Rd1"}, {.uci = "c7c6", .san = "c6"}, + {.uci = "b2b3", .san = "b3"}, {.uci = "d8e7", .san = "Qe7"}, + {.uci = "c1a3", .san = "Ba3"}, {.uci = "e5e4", .san = "e4"}, + {.uci = "f3g5", .san = "Ng5"}, {.uci = "e4e3", .san = "e3"}, + {.uci = "f2f4", .san = "f4"}, {.uci = "d7f8", .san = "Nf8"}, + {.uci = "b3b4", .san = "b4"}, {.uci = "c8f5", .san = "Bf5"}, + {.uci = "c2b3", .san = "Qb3"}, {.uci = "h7h6", .san = "h6"}, + {.uci = "g5f3", .san = "Nf3"}, {.uci = "f6g4", .san = "Ng4"}, + {.uci = "b4b5", .san = "b5"}, {.uci = "g6g5", .san = "g5"}, + {.uci = "b5c6", .san = "bxc6"}, {.uci = "b7c6", .san = "bxc6"}, + {.uci = "f3e5", .san = "Ne5"}, {.uci = "g5f4", .san = "gxf4"}, + {.uci = "e5c6", .san = "Nxc6"}, {.uci = "e7g5", .san = "Qg5"}, + {.uci = "a3d6", .san = "Bxd6"}, {.uci = "f8g6", .san = "Ng6"}, + {.uci = "c3d5", .san = "Nd5"}, {.uci = "g5h5", .san = "Qh5"}, + {.uci = "h2h4", .san = "h4"}, {.uci = "g6h4", .san = "Nxh4"}, + {.uci = "g3h4", .san = "gxh4"}, {.uci = "h5h4", .san = "Qxh4"}, + {.uci = "d5e7", .san = "Nde7+"}, {.uci = "g8h8", .san = "Kh8"}, + {.uci = "e7f5", .san = "Nxf5"}, {.uci = "h4h2", .san = "Qh2+"}, + {.uci = "g1f1", .san = "Kf1"}, {.uci = "e8e6", .san = "Re6"}, + {.uci = "b3b7", .san = "Qb7"}, {.uci = "e6g6", .san = "Rg6"}, + {.uci = "b7a8", .san = "Qxa8+"}, {.uci = "h8h7", .san = "Kh7"}, + {.uci = "a8g8", .san = "Qg8+"}, {.uci = "h7g8", .san = "Kxg8"}, + {.uci = "c6e7", .san = "Nce7+"}, {.uci = "g8h7", .san = "Kh7"}, + {.uci = "e7g6", .san = "Nxg6"}, {.uci = "f7g6", .san = "fxg6"}, + {.uci = "f5g7", .san = "Nxg7"}, {.uci = "g4f2", .san = "Nf2"}, + {.uci = "d6f4", .san = "Bxf4"}, {.uci = "h2f4", .san = "Qxf4"}, + {.uci = "g7e6", .san = "Ne6"}, {.uci = "f4h2", .san = "Qh2"}, + {.uci = "d1b1", .san = "Rdb1"}, {.uci = "f2h3", .san = "Nh3"}, + {.uci = "b1b7", .san = "Rb7+"}, {.uci = "h7h8", .san = "Kh8"}, + {.uci = "b7b8", .san = "Rb8+"}, {.uci = "h2b8", .san = "Qxb8"}, + {.uci = "g2h3", .san = "Bxh3"}, {.uci = "b8g3", .san = "Qg3"}, + }}, + {.desc = "M. Krasenkow / H. Nakamura / 2007 / Barcelona", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 56, + .moves = + { + {.uci = "g1f3", .san = "Nf3"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "g2g3", .san = "g3"}, {.uci = "d7d5", .san = "d5"}, + {.uci = "f1g2", .san = "Bg2"}, {.uci = "f8e7", .san = "Be7"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "b2b3", .san = "b3"}, {.uci = "a7a5", .san = "a5"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "c7c6", .san = "c6"}, + {.uci = "d2d4", .san = "d4"}, {.uci = "b8d7", .san = "Nbd7"}, + {.uci = "d1c2", .san = "Qc2"}, {.uci = "b7b6", .san = "b6"}, + {.uci = "e2e4", .san = "e4"}, {.uci = "c8a6", .san = "Ba6"}, + {.uci = "f3d2", .san = "Nd2"}, {.uci = "c6c5", .san = "c5"}, + {.uci = "e4d5", .san = "exd5"}, {.uci = "c5d4", .san = "cxd4"}, + {.uci = "c3b5", .san = "Nb5"}, {.uci = "e6d5", .san = "exd5"}, + {.uci = "b5d4", .san = "Nxd4"}, {.uci = "a8c8", .san = "Rc8"}, + {.uci = "f1e1", .san = "Re1"}, {.uci = "b6b5", .san = "b5"}, + {.uci = "c1b2", .san = "Bb2"}, {.uci = "f8e8", .san = "Re8"}, + {.uci = "c2d1", .san = "Qd1"}, {.uci = "b5c4", .san = "bxc4"}, + {.uci = "b3c4", .san = "bxc4"}, {.uci = "d8b6", .san = "Qb6"}, + {.uci = "a1b1", .san = "Rb1"}, {.uci = "d5c4", .san = "dxc4"}, + {.uci = "d4c6", .san = "Nc6"}, {.uci = "c8c6", .san = "Rxc6"}, + {.uci = "b2f6", .san = "Bxf6"}, {.uci = "b6f2", .san = "Qxf2+"}, + {.uci = "g1f2", .san = "Kxf2"}, {.uci = "e7c5", .san = "Bc5+"}, + {.uci = "f2f3", .san = "Kf3"}, {.uci = "c6f6", .san = "Rxf6+"}, + {.uci = "f3g4", .san = "Kg4"}, {.uci = "d7e5", .san = "Ne5+"}, + {.uci = "g4g5", .san = "Kg5"}, {.uci = "f6g6", .san = "Rg6+"}, + {.uci = "g5h5", .san = "Kh5"}, {.uci = "f7f6", .san = "f6"}, + {.uci = "e1e5", .san = "Rxe5"}, {.uci = "e8e5", .san = "Rxe5+"}, + {.uci = "h5h4", .san = "Kh4"}, {.uci = "a6c8", .san = "Bc8"}, + }}, + {.desc = "A. Karpov / V. Topalov / 1994\n\"Karpov's immortal\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 77, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "c7c5", .san = "c5"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "c5d4", .san = "cxd4"}, + {.uci = "f3d4", .san = "Nxd4"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "g2g3", .san = "g3"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "f1g2", .san = "Bg2"}, {.uci = "f8c5", .san = "Bc5"}, + {.uci = "d4b3", .san = "Nb3"}, {.uci = "c5e7", .san = "Be7"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "d7d6", .san = "d6"}, + {.uci = "c1f4", .san = "Bf4"}, {.uci = "f6h5", .san = "Nh5"}, + {.uci = "e2e3", .san = "e3"}, {.uci = "h5f4", .san = "Nxf4"}, + {.uci = "e3f4", .san = "exf4"}, {.uci = "c8d7", .san = "Bd7"}, + {.uci = "d1d2", .san = "Qd2"}, {.uci = "d8b8", .san = "Qb8"}, + {.uci = "f1e1", .san = "Rfe1"}, {.uci = "g7g6", .san = "g6"}, + {.uci = "h2h4", .san = "h4"}, {.uci = "a7a6", .san = "a6"}, + {.uci = "h4h5", .san = "h5"}, {.uci = "b7b5", .san = "b5"}, + {.uci = "h5g6", .san = "hxg6"}, {.uci = "h7g6", .san = "hxg6"}, + {.uci = "b3c5", .san = "Nc5"}, {.uci = "d6c5", .san = "dxc5"}, + {.uci = "d2d7", .san = "Qxd7"}, {.uci = "f8c8", .san = "Rc8"}, + {.uci = "e1e6", .san = "Rxe6"}, {.uci = "a8a7", .san = "Ra7"}, + {.uci = "e6g6", .san = "Rxg6+"}, {.uci = "f7g6", .san = "fxg6"}, + {.uci = "d7e6", .san = "Qe6+"}, {.uci = "g8g7", .san = "Kg7"}, + {.uci = "g2c6", .san = "Bxc6"}, {.uci = "c8d8", .san = "Rd8"}, + {.uci = "c4b5", .san = "cxb5"}, {.uci = "e7f6", .san = "Bf6"}, + {.uci = "c3e4", .san = "Ne4"}, {.uci = "f6d4", .san = "Bd4"}, + {.uci = "b5a6", .san = "bxa6"}, {.uci = "b8b6", .san = "Qb6"}, + {.uci = "a1d1", .san = "Rd1"}, {.uci = "b6a6", .san = "Qxa6"}, + {.uci = "d1d4", .san = "Rxd4"}, {.uci = "d8d4", .san = "Rxd4"}, + {.uci = "e6f6", .san = "Qf6+"}, {.uci = "g7g8", .san = "Kg8"}, + {.uci = "f6g6", .san = "Qxg6+"}, {.uci = "g8f8", .san = "Kf8"}, + {.uci = "g6e8", .san = "Qe8+"}, {.uci = "f8g7", .san = "Kg7"}, + {.uci = "e8e5", .san = "Qe5+"}, {.uci = "g7g8", .san = "Kg8"}, + {.uci = "e4f6", .san = "Nf6+"}, {.uci = "g8f7", .san = "Kf7"}, + {.uci = "c6e8", .san = "Be8+"}, {.uci = "f7f8", .san = "Kf8"}, + {.uci = "e5c5", .san = "Qxc5+"}, {.uci = "a6d6", .san = "Qd6"}, + {.uci = "c5a7", .san = "Qxa7"}, {.uci = "d6f6", .san = "Qxf6"}, + {.uci = "e8h5", .san = "Bh5"}, {.uci = "d4d2", .san = "Rd2"}, + {.uci = "b2b3", .san = "b3"}, {.uci = "d2b2", .san = "Rb2"}, + {.uci = "g1g2", .san = "Kg2"}, + }}, + {.desc = "M. Carlsen / S. Ernst / 2004\n\"The Magnus effect\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 57, + .moves = + { + {.uci = "e2e4", .san = "e4"}, {.uci = "c7c6", .san = "c6"}, + {.uci = "d2d4", .san = "d4"}, {.uci = "d7d5", .san = "d5"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "d5e4", .san = "dxe4"}, + {.uci = "c3e4", .san = "Nxe4"}, {.uci = "c8f5", .san = "Bf5"}, + {.uci = "e4g3", .san = "Ng3"}, {.uci = "f5g6", .san = "Bg6"}, + {.uci = "h2h4", .san = "h4"}, {.uci = "h7h6", .san = "h6"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "b8d7", .san = "Nd7"}, + {.uci = "h4h5", .san = "h5"}, {.uci = "g6h7", .san = "Bh7"}, + {.uci = "f1d3", .san = "Bd3"}, {.uci = "h7d3", .san = "Bxd3"}, + {.uci = "d1d3", .san = "Qxd3"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "c1f4", .san = "Bf4"}, {.uci = "g8f6", .san = "Ngf6"}, + {.uci = "e1c1", .san = "O-O-O"}, {.uci = "f8e7", .san = "Be7"}, + {.uci = "g3e4", .san = "Ne4"}, {.uci = "d8a5", .san = "Qa5"}, + {.uci = "c1b1", .san = "Kb1"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "e4f6", .san = "Nxf6+"}, {.uci = "d7f6", .san = "Nxf6"}, + {.uci = "f3e5", .san = "Ne5"}, {.uci = "a8d8", .san = "Rad8"}, + {.uci = "d3e2", .san = "Qe2"}, {.uci = "c6c5", .san = "c5"}, + {.uci = "e5g6", .san = "Ng6"}, {.uci = "f7g6", .san = "fxg6"}, + {.uci = "e2e6", .san = "Qxe6+"}, {.uci = "g8h8", .san = "Kh8"}, + {.uci = "h5g6", .san = "hxg6"}, {.uci = "f6g8", .san = "Ng8"}, + {.uci = "f4h6", .san = "Bxh6"}, {.uci = "g7h6", .san = "gxh6"}, + {.uci = "h1h6", .san = "Rxh6+"}, {.uci = "g8h6", .san = "Nxh6"}, + {.uci = "e6e7", .san = "Qxe7"}, {.uci = "h6f7", .san = "Nf7"}, + {.uci = "g6f7", .san = "gxf7"}, {.uci = "h8g7", .san = "Kg7"}, + {.uci = "d1d3", .san = "Rd3"}, {.uci = "d8d6", .san = "Rd6"}, + {.uci = "d3g3", .san = "Rg3+"}, {.uci = "d6g6", .san = "Rg6"}, + {.uci = "e7e5", .san = "Qe5+"}, {.uci = "g7f7", .san = "Kxf7"}, + {.uci = "e5f5", .san = "Qf5+"}, {.uci = "g6f6", .san = "Rf6"}, + {.uci = "f5d7", .san = "Qd7#"}, + }}, + {.desc = "N. Short / J. Timman / 1991\n\"The king's walk\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 67, + .moves = + { + {.uci = "e2e4", .san = "e4"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "e4e5", .san = "e5"}, {.uci = "f6d5", .san = "Nd5"}, + {.uci = "d2d4", .san = "d4"}, {.uci = "d7d6", .san = "d6"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "g7g6", .san = "g6"}, + {.uci = "f1c4", .san = "Bc4"}, {.uci = "d5b6", .san = "Nb6"}, + {.uci = "c4b3", .san = "Bb3"}, {.uci = "f8g7", .san = "Bg7"}, + {.uci = "d1e2", .san = "Qe2"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "h2h3", .san = "h3"}, {.uci = "a7a5", .san = "a5"}, + {.uci = "a2a4", .san = "a4"}, {.uci = "d6e5", .san = "dxe5"}, + {.uci = "d4e5", .san = "dxe5"}, {.uci = "c6d4", .san = "Nd4"}, + {.uci = "f3d4", .san = "Nxd4"}, {.uci = "d8d4", .san = "Qxd4"}, + {.uci = "f1e1", .san = "Re1"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "b1d2", .san = "Nd2"}, {.uci = "b6d5", .san = "Nd5"}, + {.uci = "d2f3", .san = "Nf3"}, {.uci = "d4c5", .san = "Qc5"}, + {.uci = "e2e4", .san = "Qe4"}, {.uci = "c5b4", .san = "Qb4"}, + {.uci = "b3c4", .san = "Bc4"}, {.uci = "d5b6", .san = "Nb6"}, + {.uci = "b2b3", .san = "b3"}, {.uci = "b6c4", .san = "Nxc4"}, + {.uci = "b3c4", .san = "bxc4"}, {.uci = "f8e8", .san = "Re8"}, + {.uci = "e1d1", .san = "Rd1"}, {.uci = "b4c5", .san = "Qc5"}, + {.uci = "e4h4", .san = "Qh4"}, {.uci = "b7b6", .san = "b6"}, + {.uci = "c1e3", .san = "Be3"}, {.uci = "c5c6", .san = "Qc6"}, + {.uci = "e3h6", .san = "Bh6"}, {.uci = "g7h8", .san = "Bh8"}, + {.uci = "d1d8", .san = "Rd8"}, {.uci = "c8b7", .san = "Bb7"}, + {.uci = "a1d1", .san = "Rad1"}, {.uci = "h8g7", .san = "Bg7"}, + {.uci = "d8d7", .san = "R8d7"}, {.uci = "e8f8", .san = "Rf8"}, + {.uci = "h6g7", .san = "Bxg7"}, {.uci = "g8g7", .san = "Kxg7"}, + {.uci = "d1d4", .san = "R1d4"}, {.uci = "a8e8", .san = "Rae8"}, + {.uci = "h4f6", .san = "Qf6+"}, {.uci = "g7g8", .san = "Kg8"}, + {.uci = "h3h4", .san = "h4"}, {.uci = "h7h5", .san = "h5"}, + {.uci = "g1h2", .san = "Kh2"}, {.uci = "e8c8", .san = "Rc8"}, + {.uci = "h2g3", .san = "Kg3"}, {.uci = "c8e8", .san = "Rce8"}, + {.uci = "g3f4", .san = "Kf4"}, {.uci = "b7c8", .san = "Bc8"}, + {.uci = "f4g5", .san = "Kg5"}, + }}, + {.desc = "L. Aronian / V. Anand / 2013\n\"Nerves of steel\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 46, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "d7d5", .san = "d5"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "c7c6", .san = "c6"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "e2e3", .san = "e3"}, {.uci = "b8d7", .san = "Nbd7"}, + {.uci = "f1d3", .san = "Bd3"}, {.uci = "d5c4", .san = "dxc4"}, + {.uci = "d3c4", .san = "Bxc4"}, {.uci = "b7b5", .san = "b5"}, + {.uci = "c4d3", .san = "Bd3"}, {.uci = "f8d6", .san = "Bd6"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "d1c2", .san = "Qc2"}, {.uci = "c8b7", .san = "Bb7"}, + {.uci = "a2a3", .san = "a3"}, {.uci = "a8c8", .san = "Rc8"}, + {.uci = "f3g5", .san = "Ng5"}, {.uci = "c6c5", .san = "c5"}, + {.uci = "g5h7", .san = "Nxh7"}, {.uci = "f6g4", .san = "Ng4"}, + {.uci = "f2f4", .san = "f4"}, {.uci = "c5d4", .san = "cxd4"}, + {.uci = "e3d4", .san = "exd4"}, {.uci = "d6c5", .san = "Bc5"}, + {.uci = "d3e2", .san = "Be2"}, {.uci = "d7e5", .san = "Nde5"}, + {.uci = "e2g4", .san = "Bxg4"}, {.uci = "c5d4", .san = "Bxd4+"}, + {.uci = "g1h1", .san = "Kh1"}, {.uci = "e5g4", .san = "Nxg4"}, + {.uci = "h7f8", .san = "Nxf8"}, {.uci = "f7f5", .san = "f5"}, + {.uci = "f8g6", .san = "Ng6"}, {.uci = "d8f6", .san = "Qf6"}, + {.uci = "h2h3", .san = "h3"}, {.uci = "f6g6", .san = "Qxg6"}, + {.uci = "c2e2", .san = "Qe2"}, {.uci = "g6h5", .san = "Qh5"}, + {.uci = "e2d3", .san = "Qd3"}, {.uci = "d4e3", .san = "Be3"}, + }}, + {.desc = "Jinshi Bai / Ding Liren / 2017.11.04\nChinese Chess League", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 64, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "f8b4", .san = "Bb4"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "c1g5", .san = "Bg5"}, {.uci = "c7c5", .san = "c5"}, + {.uci = "e2e3", .san = "e3"}, {.uci = "c5d4", .san = "cxd4"}, + {.uci = "d1d4", .san = "Qxd4"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "d4d3", .san = "Qd3"}, {.uci = "h7h6", .san = "h6"}, + {.uci = "g5h4", .san = "Bh4"}, {.uci = "d7d5", .san = "d5"}, + {.uci = "a1d1", .san = "Rd1"}, {.uci = "g7g5", .san = "g5"}, + {.uci = "h4g3", .san = "Bg3"}, {.uci = "f6e4", .san = "Ne4"}, + {.uci = "f3d2", .san = "Nd2"}, {.uci = "e4c5", .san = "Nc5"}, + {.uci = "d3c2", .san = "Qc2"}, {.uci = "d5d4", .san = "d4"}, + {.uci = "d2f3", .san = "Nf3"}, {.uci = "e6e5", .san = "e5"}, + {.uci = "f3e5", .san = "Nxe5"}, {.uci = "d4c3", .san = "dxc3"}, + {.uci = "d1d8", .san = "Rxd8"}, {.uci = "c3b2", .san = "cxb2+"}, + {.uci = "e1e2", .san = "Ke2"}, {.uci = "f8d8", .san = "Rxd8"}, + {.uci = "c2b2", .san = "Qxb2"}, {.uci = "c5a4", .san = "Na4"}, + {.uci = "b2c2", .san = "Qc2"}, {.uci = "a4c3", .san = "Nc3+"}, + {.uci = "e2f3", .san = "Kf3"}, {.uci = "d8d4", .san = "Rd4"}, + {.uci = "h2h3", .san = "h3"}, {.uci = "h6h5", .san = "h5"}, + {.uci = "g3h2", .san = "Bh2"}, {.uci = "g5g4", .san = "g4+"}, + {.uci = "f3g3", .san = "Kg3"}, {.uci = "d4d2", .san = "Rd2"}, + {.uci = "c2b3", .san = "Qb3"}, {.uci = "c3e4", .san = "Ne4+"}, + {.uci = "g3h4", .san = "Kh4"}, {.uci = "b4e7", .san = "Be7+"}, + {.uci = "h4h5", .san = "Kxh5"}, {.uci = "g8g7", .san = "Kg7"}, + {.uci = "h2f4", .san = "Bf4"}, {.uci = "c8f5", .san = "Bf5"}, + {.uci = "f4h6", .san = "Bh6+"}, {.uci = "g7h7", .san = "Kh7"}, + {.uci = "b3b7", .san = "Qxb7"}, {.uci = "d2f2", .san = "Rxf2"}, + {.uci = "h6g5", .san = "Bg5"}, {.uci = "a8h8", .san = "Rh8"}, + {.uci = "e5f7", .san = "Nxf7"}, {.uci = "f5g6", .san = "Bg6+"}, + {.uci = "h5g4", .san = "Kxg4"}, {.uci = "c6e5", .san = "Ne5+"}, + }}, + {.desc = "E. Geller / M. Euwe / 1953.08.31", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 52, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "f8b4", .san = "Bb4"}, + {.uci = "e2e3", .san = "e3"}, {.uci = "c7c5", .san = "c5"}, + {.uci = "a2a3", .san = "a3"}, {.uci = "b4c3", .san = "Bxc3+"}, + {.uci = "b2c3", .san = "bxc3"}, {.uci = "b7b6", .san = "b6"}, + {.uci = "f1d3", .san = "Bd3"}, {.uci = "c8b7", .san = "Bb7"}, + {.uci = "f2f3", .san = "f3"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "g1e2", .san = "Ne2"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "c6a5", .san = "Na5"}, + {.uci = "e3e4", .san = "e4"}, {.uci = "f6e8", .san = "Ne8"}, + {.uci = "e2g3", .san = "Ng3"}, {.uci = "c5d4", .san = "cxd4"}, + {.uci = "c3d4", .san = "cxd4"}, {.uci = "a8c8", .san = "Rc8"}, + {.uci = "f3f4", .san = "f4"}, {.uci = "a5c4", .san = "Nxc4"}, + {.uci = "f4f5", .san = "f5"}, {.uci = "f7f6", .san = "f6"}, + {.uci = "f1f4", .san = "Rf4"}, {.uci = "b6b5", .san = "b5"}, + {.uci = "f4h4", .san = "Rh4"}, {.uci = "d8b6", .san = "Qb6"}, + {.uci = "e4e5", .san = "e5"}, {.uci = "c4e5", .san = "Nxe5"}, + {.uci = "f5e6", .san = "fxe6"}, {.uci = "e5d3", .san = "Nxd3"}, + {.uci = "d1d3", .san = "Qxd3"}, {.uci = "b6e6", .san = "Qxe6"}, + {.uci = "d3h7", .san = "Qxh7+"}, {.uci = "g8f7", .san = "Kf7"}, + {.uci = "c1h6", .san = "Bh6"}, {.uci = "f8h8", .san = "Rh8"}, + {.uci = "h7h8", .san = "Qxh8"}, {.uci = "c8c2", .san = "Rc2"}, + {.uci = "a1c1", .san = "Rc1"}, {.uci = "c2g2", .san = "Rxg2+"}, + {.uci = "g1f1", .san = "Kf1"}, {.uci = "e6b3", .san = "Qb3"}, + {.uci = "f1e1", .san = "Ke1"}, {.uci = "b3f3", .san = "Qf3"}, + }}, + {.desc = "S. Levitsky / F. J. Marshall / 1912\n\"The Gold coin game\"", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 46, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "e2e4", .san = "e4"}, {.uci = "d7d5", .san = "d5"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "c7c5", .san = "c5"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "b8c6", .san = "Nc6"}, + {.uci = "e4d5", .san = "exd5"}, {.uci = "e6d5", .san = "exd5"}, + {.uci = "f1e2", .san = "Be2"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "f8e7", .san = "Be7"}, + {.uci = "c1g5", .san = "Bg5"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "d4c5", .san = "dxc5"}, {.uci = "c8e6", .san = "Be6"}, + {.uci = "f3d4", .san = "Nd4"}, {.uci = "e7c5", .san = "Bxc5"}, + {.uci = "d4e6", .san = "Nxe6"}, {.uci = "f7e6", .san = "fxe6"}, + {.uci = "e2g4", .san = "Bg4"}, {.uci = "d8d6", .san = "Qd6"}, + {.uci = "g4h3", .san = "Bh3"}, {.uci = "a8e8", .san = "Rae8"}, + {.uci = "d1d2", .san = "Qd2"}, {.uci = "c5b4", .san = "Bb4"}, + {.uci = "g5f6", .san = "Bxf6"}, {.uci = "f8f6", .san = "Rxf6"}, + {.uci = "a1d1", .san = "Rad1"}, {.uci = "d6c5", .san = "Qc5"}, + {.uci = "d2e2", .san = "Qe2"}, {.uci = "b4c3", .san = "Bxc3"}, + {.uci = "b2c3", .san = "bxc3"}, {.uci = "c5c3", .san = "Qxc3"}, + {.uci = "d1d5", .san = "Rxd5"}, {.uci = "c6d4", .san = "Nd4"}, + {.uci = "e2h5", .san = "Qh5"}, {.uci = "e8f8", .san = "Ref8"}, + {.uci = "d5e5", .san = "Re5"}, {.uci = "f6h6", .san = "Rh6"}, + {.uci = "h5g5", .san = "Qg5"}, {.uci = "h6h3", .san = "Rxh3"}, + {.uci = "e5c5", .san = "Rc5"}, {.uci = "c3g3", .san = "Qg3"}, + }}, + {.desc = "E. N. Somov-Nasimovitsch / 1928 / Zadachi I Etiudi", + .fen = "5k2/p1p1p3/2p1p2N/P1R5/P3KP2/8/p6P/b7", + .movecount = 19, + .moves = + { + {.uci = "c5c2", .san = "Rc2"}, {.uci = "a1b2", .san = "Bb2"}, + {.uci = "c2g2", .san = "Rg2"}, {.uci = "f8e8", .san = "Ke8"}, + {.uci = "g2g8", .san = "Rg8+"}, {.uci = "e8d7", .san = "Kd7"}, + {.uci = "h6f7", .san = "Nf7"}, {.uci = "c6c5", .san = "c5"}, + {.uci = "g8d8", .san = "Rd8+"}, {.uci = "d7c6", .san = "Kc6"}, + {.uci = "d8d2", .san = "Rd2"}, {.uci = "c5c4", .san = "c4"}, + {.uci = "f7d8", .san = "Nd8+"}, {.uci = "c6c5", .san = "Kc5"}, + {.uci = "d8e6", .san = "Nxe6+"}, {.uci = "c5c6", .san = "Kc6"}, + {.uci = "e6d8", .san = "Nd8+"}, {.uci = "c6c5", .san = "Kc5"}, + {.uci = "d2b2", .san = "Rxb2"}, + }}, + {.desc = "J. Hendel / 1859\nPayne's family journal", + .fen = "8/K1N1p3/2k1N3/4P3/8/8/1P6/8", + .movecount = 9, + .moves = + { + {.uci = "b2b4", .san = "b4"}, + {.uci = "c6d7", .san = "Kd7"}, + {.uci = "b4b5", .san = "b5"}, + {.uci = "d7c8", .san = "Kc8"}, + {.uci = "b5b6", .san = "b6"}, + {.uci = "c8d7", .san = "Kd7"}, + {.uci = "b6b7", .san = "b7"}, + {.uci = "d7c6", .san = "Kc6"}, + {.uci = "b7b8n", .san = "b8=N#"}, + }}, + {.desc = "J. Hasek / 1929\nLa strategie", + .fen = "3N3N/1Kpp4/8/1k6/1P3p2/P1P5/8/8", + .movecount = 9, + .moves = + { + {.uci = "d8c6", .san = "Nc6"}, + {.uci = "d7c6", .san = "dxc6"}, + {.uci = "h8g6", .san = "Ng6"}, + {.uci = "f4f3", .san = "f3"}, + {.uci = "g6e5", .san = "Ne5"}, + {.uci = "f3f2", .san = "f2"}, + {.uci = "e5d3", .san = "Nd3"}, + {.uci = "f2f1q", .san = "f1=Q"}, + {.uci = "d3b2", .san = "Nb2"}, + }}, + {.desc = "K. A. L. Kubbel / 1936\nChess in the USSR", + .fen = "8/7p/4pK1k/5R2/8/1b2r1P1/8/5B2", + .movecount = 9, + .moves = + { + {.uci = "f5f2", .san = "Rf2"}, + {.uci = "b3d1", .san = "Bd1"}, + {.uci = "f2h2", .san = "Rh2"}, + {.uci = "d1h5", .san = "Bh5"}, + {.uci = "f1e2", .san = "Be2"}, + {.uci = "e3e2", .san = "Rxe2"}, + {.uci = "g3g4", .san = "g4"}, + {.uci = "e2h2", .san = "Rxh2"}, + {.uci = "g4g5", .san = "g5"}, + }}, + {.desc = "M. B. Newman / 1913\nChess amateur", + .fen = "4q3/n7/8/7P/k1B1N3/P3N3/8/K7", + .movecount = 11, + .moves = + { + {.uci = "c4b5", .san = "Bb5+"}, + {.uci = "e8b5", .san = "Qxb5"}, + {.uci = "e4c3", .san = "Nc3+"}, + {.uci = "a4a3", .san = "Kxa3"}, + {.uci = "c3b5", .san = "Nxb5+"}, + {.uci = "a7b5", .san = "Nxb5"}, + {.uci = "h5h6", .san = "h6"}, + {.uci = "b5d6", .san = "Nd6"}, + {.uci = "e3c4", .san = "Nc4+"}, + {.uci = "d6c4", .san = "Nxc4"}, + {.uci = "h6h7", .san = "h7"}, + }}, + {.desc = "V. A. Korolikov / 1935 / Truda", + .fen = "2B5/pR6/2pP1k2/8/6Kb/4p1P1/5p2/8", + .movecount = 19, + .moves = + { + {.uci = "d6d7", .san = "d7"}, {.uci = "f6e7", .san = "Ke7"}, + {.uci = "b7b8", .san = "Rb8"}, {.uci = "h4g3", .san = "Bxg3"}, + {.uci = "b8a8", .san = "Ra8"}, {.uci = "f2f1q", .san = "f1=Q"}, + {.uci = "d7d8q", .san = "d8=Q+"}, {.uci = "e7d8", .san = "Kxd8"}, + {.uci = "c8a6", .san = "Ba6+"}, {.uci = "g3b8", .san = "Bb8"}, + {.uci = "a6f1", .san = "Bxf1"}, {.uci = "d8c7", .san = "Kc7"}, + {.uci = "f1a6", .san = "Ba6"}, {.uci = "e3e2", .san = "e2"}, + {.uci = "a6e2", .san = "Bxe2"}, {.uci = "c7b7", .san = "Kb7"}, + {.uci = "e2f3", .san = "Bf3"}, {.uci = "b7a8", .san = "Kxa8"}, + {.uci = "f3c6", .san = "Bxc6#"}, + }}, + {.desc = "Gorgiev / 1929 / 64", + .fen = "6N1/n7/3kn3/K7/6N1/8/8/4B3", + .movecount = 11, + .moves = + { + {.uci = "a5b6", .san = "Kb6"}, + {.uci = "a7c8", .san = "Nc8+"}, + {.uci = "b6b7", .san = "Kb7"}, + {.uci = "c8e7", .san = "Ne7"}, + {.uci = "e1g3", .san = "Bg3+"}, + {.uci = "d6d7", .san = "Kd7"}, + {.uci = "g8f6", .san = "N8f6+"}, + {.uci = "d7d8", .san = "Kd8"}, + {.uci = "g3c7", .san = "Bc7+"}, + {.uci = "e6c7", .san = "Nxc7"}, + {.uci = "g4e5", .san = "Ne5"}, + }}, + {.desc = "K. A. L. Kubbel / 1922\nSchachmatny Listok", + .fen = "1N6/8/K7/3k4/3p3B/p7/2PP4/8", + .movecount = 11, + .moves = + { + {.uci = "b8c6", .san = "Nc6"}, + {.uci = "d5c6", .san = "Kxc6"}, + {.uci = "h4f6", .san = "Bf6"}, + {.uci = "c6d5", .san = "Kd5"}, + {.uci = "d2d3", .san = "d3"}, + {.uci = "a3a2", .san = "a2"}, + {.uci = "c2c4", .san = "c4+"}, + {.uci = "d5c5", .san = "Kc5"}, + {.uci = "a6b7", .san = "Kb7"}, + {.uci = "a2a1q", .san = "a1=Q"}, + {.uci = "f6e7", .san = "Be7#"}, + }}, + {.desc = "M. Carlsen / G. Kasparov / 2004 / Reykjavik", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 103, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "d7d5", .san = "d5"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "c7c6", .san = "c6"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "c1g5", .san = "Bg5"}, {.uci = "b8d7", .san = "Nbd7"}, + {.uci = "e2e3", .san = "e3"}, {.uci = "d8a5", .san = "Qa5"}, + {.uci = "f3d2", .san = "Nd2"}, {.uci = "f8b4", .san = "Bb4"}, + {.uci = "d1c2", .san = "Qc2"}, {.uci = "e8g8", .san = "O-O"}, + {.uci = "f1e2", .san = "Be2"}, {.uci = "e6e5", .san = "e5"}, + {.uci = "e1g1", .san = "O-O"}, {.uci = "e5d4", .san = "exd4"}, + {.uci = "d2b3", .san = "Nb3"}, {.uci = "a5b6", .san = "Qb6"}, + {.uci = "e3d4", .san = "exd4"}, {.uci = "d5c4", .san = "dxc4"}, + {.uci = "e2c4", .san = "Bxc4"}, {.uci = "a7a5", .san = "a5"}, + {.uci = "a2a4", .san = "a4"}, {.uci = "b6c7", .san = "Qc7"}, + {.uci = "a1e1", .san = "Rae1"}, {.uci = "h7h6", .san = "h6"}, + {.uci = "g5h4", .san = "Bh4"}, {.uci = "b4d6", .san = "Bd6"}, + {.uci = "h2h3", .san = "h3"}, {.uci = "d7b6", .san = "Nb6"}, + {.uci = "h4f6", .san = "Bxf6"}, {.uci = "b6c4", .san = "Nxc4"}, + {.uci = "c3e4", .san = "Ne4"}, {.uci = "d6h2", .san = "Bh2+"}, + {.uci = "g1h1", .san = "Kh1"}, {.uci = "c4d6", .san = "Nd6"}, + {.uci = "h1h2", .san = "Kxh2"}, {.uci = "d6e4", .san = "Nxe4+"}, + {.uci = "f6e5", .san = "Be5"}, {.uci = "e4d6", .san = "Nd6"}, + {.uci = "c2c5", .san = "Qc5"}, {.uci = "f8d8", .san = "Rd8"}, + {.uci = "d4d5", .san = "d5"}, {.uci = "c7d7", .san = "Qd7"}, + {.uci = "b3d4", .san = "Nd4"}, {.uci = "d6f5", .san = "Nf5"}, + {.uci = "d5c6", .san = "dxc6"}, {.uci = "b7c6", .san = "bxc6"}, + {.uci = "d4c6", .san = "Nxc6"}, {.uci = "d8e8", .san = "Re8"}, + {.uci = "e1d1", .san = "Rd1"}, {.uci = "d7e6", .san = "Qe6"}, + {.uci = "f1e1", .san = "Rfe1"}, {.uci = "c8b7", .san = "Bb7"}, + {.uci = "c6d4", .san = "Nd4"}, {.uci = "f5d4", .san = "Nxd4"}, + {.uci = "c5d4", .san = "Qxd4"}, {.uci = "e6g6", .san = "Qg6"}, + {.uci = "d4g4", .san = "Qg4"}, {.uci = "g6g4", .san = "Qxg4"}, + {.uci = "h3g4", .san = "hxg4"}, {.uci = "b7c6", .san = "Bc6"}, + {.uci = "b2b3", .san = "b3"}, {.uci = "f7f6", .san = "f6"}, + {.uci = "e5c3", .san = "Bc3"}, {.uci = "e8e1", .san = "Rxe1"}, + {.uci = "d1e1", .san = "Rxe1"}, {.uci = "c6d5", .san = "Bd5"}, + {.uci = "e1b1", .san = "Rb1"}, {.uci = "g8f7", .san = "Kf7"}, + {.uci = "h2g3", .san = "Kg3"}, {.uci = "a8b8", .san = "Rb8"}, + {.uci = "b3b4", .san = "b4"}, {.uci = "a5b4", .san = "axb4"}, + {.uci = "c3b4", .san = "Bxb4"}, {.uci = "d5c4", .san = "Bc4"}, + {.uci = "a4a5", .san = "a5"}, {.uci = "c4a6", .san = "Ba6"}, + {.uci = "f2f3", .san = "f3"}, {.uci = "f7g6", .san = "Kg6"}, + {.uci = "g3f4", .san = "Kf4"}, {.uci = "h6h5", .san = "h5"}, + {.uci = "g4h5", .san = "gxh5+"}, {.uci = "g6h5", .san = "Kxh5"}, + {.uci = "b1h1", .san = "Rh1+"}, {.uci = "h5g6", .san = "Kg6"}, + {.uci = "b4c5", .san = "Bc5"}, {.uci = "b8b2", .san = "Rb2"}, + {.uci = "f4g3", .san = "Kg3"}, {.uci = "b2a2", .san = "Ra2"}, + {.uci = "c5b6", .san = "Bb6"}, {.uci = "g6f7", .san = "Kf7"}, + {.uci = "h1c1", .san = "Rc1"}, {.uci = "g7g5", .san = "g5"}, + {.uci = "c1c7", .san = "Rc7+"}, {.uci = "f7g6", .san = "Kg6"}, + {.uci = "c7c6", .san = "Rc6"}, {.uci = "a6f1", .san = "Bf1"}, + {.uci = "b6f2", .san = "Bf2"}, + }}, + {.desc = "M. Carlsen / V. Kramnik / 2016 / Norway", + .fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR", + .movecount = 99, + .moves = + { + {.uci = "d2d4", .san = "d4"}, {.uci = "d7d5", .san = "d5"}, + {.uci = "c2c4", .san = "c4"}, {.uci = "e7e6", .san = "e6"}, + {.uci = "b1c3", .san = "Nc3"}, {.uci = "g8f6", .san = "Nf6"}, + {.uci = "c4d5", .san = "cxd5"}, {.uci = "e6d5", .san = "exd5"}, + {.uci = "c1g5", .san = "Bg5"}, {.uci = "c7c6", .san = "c6"}, + {.uci = "e2e3", .san = "e3"}, {.uci = "c8f5", .san = "Bf5"}, + {.uci = "d1f3", .san = "Qf3"}, {.uci = "f5g6", .san = "Bg6"}, + {.uci = "g5f6", .san = "Bxf6"}, {.uci = "d8f6", .san = "Qxf6"}, + {.uci = "f3f6", .san = "Qxf6"}, {.uci = "g7f6", .san = "gxf6"}, + {.uci = "g1f3", .san = "Nf3"}, {.uci = "b8d7", .san = "Nd7"}, + {.uci = "f3h4", .san = "Nh4"}, {.uci = "f8e7", .san = "Be7"}, + {.uci = "c3e2", .san = "Ne2"}, {.uci = "d7b6", .san = "Nb6"}, + {.uci = "e2g3", .san = "Ng3"}, {.uci = "e7b4", .san = "Bb4+"}, + {.uci = "e1d1", .san = "Kd1"}, {.uci = "b6a4", .san = "Na4"}, + {.uci = "g3f5", .san = "Ngf5"}, {.uci = "e8d7", .san = "Kd7"}, + {.uci = "a1b1", .san = "Rb1"}, {.uci = "d7e6", .san = "Ke6"}, + {.uci = "f1d3", .san = "Bd3"}, {.uci = "h8c8", .san = "Rhc8"}, + {.uci = "d1e2", .san = "Ke2"}, {.uci = "b4f8", .san = "Bf8"}, + {.uci = "g2g4", .san = "g4"}, {.uci = "c6c5", .san = "c5"}, + {.uci = "h4g2", .san = "Ng2"}, {.uci = "c5d4", .san = "cxd4"}, + {.uci = "e3d4", .san = "exd4"}, {.uci = "f8d6", .san = "Bd6"}, + {.uci = "h2h4", .san = "h4"}, {.uci = "h7h5", .san = "h5"}, + {.uci = "f5g7", .san = "Ng7+"}, {.uci = "e6e7", .san = "Ke7"}, + {.uci = "g4h5", .san = "gxh5"}, {.uci = "g6d3", .san = "Bxd3+"}, + {.uci = "e2d3", .san = "Kxd3"}, {.uci = "e7d7", .san = "Kd7"}, + {.uci = "g2e3", .san = "Ne3"}, {.uci = "a4b6", .san = "Nb6"}, + {.uci = "e3g4", .san = "Ng4"}, {.uci = "c8h8", .san = "Rh8"}, + {.uci = "h1e1", .san = "Rhe1"}, {.uci = "d6e7", .san = "Be7"}, + {.uci = "g7f5", .san = "Nf5"}, {.uci = "e7d8", .san = "Bd8"}, + {.uci = "h5h6", .san = "h6"}, {.uci = "a8c8", .san = "Rc8"}, + {.uci = "b2b3", .san = "b3"}, {.uci = "c8c6", .san = "Rc6"}, + {.uci = "g4e3", .san = "Nge3"}, {.uci = "d8c7", .san = "Bc7"}, + {.uci = "b1c1", .san = "Rbc1"}, {.uci = "c6c1", .san = "Rxc1"}, + {.uci = "e1c1", .san = "Rxc1"}, {.uci = "c7f4", .san = "Bf4"}, + {.uci = "c1c5", .san = "Rc5"}, {.uci = "d7e6", .san = "Ke6"}, + {.uci = "f5g7", .san = "Ng7+"}, {.uci = "e6d6", .san = "Kd6"}, + {.uci = "e3g4", .san = "Ng4"}, {.uci = "b6d7", .san = "Nd7"}, + {.uci = "c5c2", .san = "Rc2"}, {.uci = "f6f5", .san = "f5"}, + {.uci = "g7f5", .san = "Nxf5+"}, {.uci = "d6e6", .san = "Ke6"}, + {.uci = "f5g7", .san = "Ng7+"}, {.uci = "e6d6", .san = "Kd6"}, + {.uci = "c2e2", .san = "Re2"}, {.uci = "d6c6", .san = "Kc6"}, + {.uci = "e2e8", .san = "Re8"}, {.uci = "h8e8", .san = "Rxe8"}, + {.uci = "g7e8", .san = "Nxe8"}, {.uci = "d7f8", .san = "Nf8"}, + {.uci = "g4e5", .san = "Ne5+"}, {.uci = "f4e5", .san = "Bxe5"}, + {.uci = "d4e5", .san = "dxe5"}, {.uci = "c6d7", .san = "Kd7"}, + {.uci = "e8f6", .san = "Nf6+"}, {.uci = "d7e6", .san = "Ke6"}, + {.uci = "h4h5", .san = "h5"}, {.uci = "e6e5", .san = "Kxe5"}, + {.uci = "f6d7", .san = "Nd7+"}, {.uci = "f8d7", .san = "Nxd7"}, + {.uci = "h6h7", .san = "h7"}, {.uci = "d7c5", .san = "Nc5+"}, + {.uci = "d3e2", .san = "Ke2"}, + }}, }; #endif /* __CHESSGAMES_H__ */ From a310f12092d05063bbcefd27a7acf8a32b095b36 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:22:50 +0200 Subject: [PATCH 15/25] hacks/bsod: simplify logic --- hacks/bsod.c | 98 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 38 deletions(-) diff --git a/hacks/bsod.c b/hacks/bsod.c index c46cd8d1b..3b25d5636 100644 --- a/hacks/bsod.c +++ b/hacks/bsod.c @@ -1971,38 +1971,36 @@ windows_10_recovery (Display *dpy, Window window) } +static int qr_size = 41; +static const unsigned char qr_bits[] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x01, + 0x03,0x9A,0x70,0xEE,0x80,0x01,0xFB,0x22,0xAA,0xA6,0xBE,0x01, + 0x8B,0x8E,0x74,0xE7,0xA2,0x01,0x8B,0xEE,0x42,0xC4,0xA2,0x01, + 0x8B,0x42,0x6E,0xED,0xA2,0x01,0xFB,0xDA,0x63,0xA6,0xBE,0x01, + 0x03,0xAA,0xAA,0xAA,0x80,0x01,0xFF,0x8B,0xD8,0x9D,0xFF,0x01, + 0x63,0x62,0xDA,0x1B,0x98,0x01,0x6F,0x67,0x98,0x9F,0xBC,0x01, + 0x4F,0xCC,0x55,0x81,0x83,0x01,0xB7,0x6D,0xFF,0x68,0xB2,0x01, + 0xC3,0x10,0x87,0x8B,0x96,0x01,0x6F,0xB1,0x91,0x58,0x94,0x01, + 0xE3,0x36,0x88,0x84,0xB8,0x01,0x83,0x9B,0xFE,0x59,0xD7,0x01, + 0x3B,0x74,0x98,0x5C,0xB4,0x01,0x37,0x75,0xDC,0x91,0xA6,0x01, + 0x77,0xDE,0x01,0x54,0xBA,0x01,0xBB,0x6D,0x8B,0xB9,0xB5,0x01, + 0x1F,0x06,0xBD,0x9B,0xB4,0x01,0xD3,0xBD,0x91,0x19,0x84,0x01, + 0x0B,0x20,0xD8,0x91,0xB4,0x01,0x33,0x95,0xBC,0x0A,0xD5,0x01, + 0xB3,0x60,0xDC,0xD9,0xB6,0x01,0xEF,0x77,0x18,0x09,0xA4,0x01, + 0xA3,0xC2,0x95,0x51,0xB2,0x01,0xDF,0x63,0xDB,0xBE,0xB3,0x01, + 0x03,0x08,0xC9,0x09,0xF0,0x01,0xFF,0xA3,0x19,0xBD,0xFB,0x01, + 0x03,0x2E,0x84,0xA5,0xAA,0x01,0xFB,0x9A,0xFC,0x9B,0xBB,0x01, + 0x8B,0x7E,0x9C,0x1D,0xB0,0x01,0x8B,0x6E,0x58,0xA1,0xDB,0x01, + 0x8B,0xDA,0xD5,0x65,0xA2,0x01,0xFB,0x72,0xFB,0xE9,0xF0,0x01, + 0x03,0x02,0x99,0x3B,0xB3,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x01, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x01}; + static struct bsod_state * windows_10 (Display *dpy, Window window) { struct bsod_state *bst = make_bsod_state (dpy, window, "win10", "Win10"); - - int qr_width = 41; - int qr_height = 41; - static const unsigned char qr_bits[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x01, - 0x03,0x9A,0x70,0xEE,0x80,0x01,0xFB,0x22,0xAA,0xA6,0xBE,0x01, - 0x8B,0x8E,0x74,0xE7,0xA2,0x01,0x8B,0xEE,0x42,0xC4,0xA2,0x01, - 0x8B,0x42,0x6E,0xED,0xA2,0x01,0xFB,0xDA,0x63,0xA6,0xBE,0x01, - 0x03,0xAA,0xAA,0xAA,0x80,0x01,0xFF,0x8B,0xD8,0x9D,0xFF,0x01, - 0x63,0x62,0xDA,0x1B,0x98,0x01,0x6F,0x67,0x98,0x9F,0xBC,0x01, - 0x4F,0xCC,0x55,0x81,0x83,0x01,0xB7,0x6D,0xFF,0x68,0xB2,0x01, - 0xC3,0x10,0x87,0x8B,0x96,0x01,0x6F,0xB1,0x91,0x58,0x94,0x01, - 0xE3,0x36,0x88,0x84,0xB8,0x01,0x83,0x9B,0xFE,0x59,0xD7,0x01, - 0x3B,0x74,0x98,0x5C,0xB4,0x01,0x37,0x75,0xDC,0x91,0xA6,0x01, - 0x77,0xDE,0x01,0x54,0xBA,0x01,0xBB,0x6D,0x8B,0xB9,0xB5,0x01, - 0x1F,0x06,0xBD,0x9B,0xB4,0x01,0xD3,0xBD,0x91,0x19,0x84,0x01, - 0x0B,0x20,0xD8,0x91,0xB4,0x01,0x33,0x95,0xBC,0x0A,0xD5,0x01, - 0xB3,0x60,0xDC,0xD9,0xB6,0x01,0xEF,0x77,0x18,0x09,0xA4,0x01, - 0xA3,0xC2,0x95,0x51,0xB2,0x01,0xDF,0x63,0xDB,0xBE,0xB3,0x01, - 0x03,0x08,0xC9,0x09,0xF0,0x01,0xFF,0xA3,0x19,0xBD,0xFB,0x01, - 0x03,0x2E,0x84,0xA5,0xAA,0x01,0xFB,0x9A,0xFC,0x9B,0xBB,0x01, - 0x8B,0x7E,0x9C,0x1D,0xB0,0x01,0x8B,0x6E,0x58,0xA1,0xDB,0x01, - 0x8B,0xDA,0xD5,0x65,0xA2,0x01,0xFB,0x72,0xFB,0xE9,0xF0,0x01, - 0x03,0x02,0x99,0x3B,0xB3,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x01, - 0xFF,0xFF,0xFF,0xFF,0xFF,0x01}; Pixmap pixmap; - const char * const lines1[] = { ":(", @@ -2068,6 +2066,7 @@ windows_10 (Display *dpy, Window window) Bool honorp = !clownp && !(random() % 20); const char * const * lines = (clownp ? lines2 : honorp ? lines3 : lines1); int stop = 60 + (random() % 39) + (clownp ? 1300 : 0); + int qs = qr_size; if (!(random() % 4)) return windows_10_recovery (dpy, window); @@ -2088,7 +2087,7 @@ windows_10 (Display *dpy, Window window) } pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) qr_bits, - qr_width, qr_height, + qs, qs, bst->fg, bst->bg, bst->xgwa.depth); { int n = 2; @@ -2097,9 +2096,8 @@ windows_10 (Display *dpy, Window window) for (i = 0; i < n; i++) { pixmap = double_pixmap (dpy, bst->xgwa.visual, bst->xgwa.depth, - pixmap, qr_width, qr_height); - qr_width *= 2; - qr_height *= 2; + pixmap, qs, qs); + qs *= 2; } } bst->pixmap = pixmap; @@ -2140,14 +2138,14 @@ windows_10 (Display *dpy, Window window) } else if (i == 2) { - left += qr_width + font->ascent / 2; + left += qs + font->ascent / 2; if (bst->xgwa.width > bst->xgwa.height) - right += qr_width * 1.8; + right += qs * 1.8; BSOD_MARGINS (bst, left, right); } else if (i == 3) { - BSOD_PIXMAP (bst, 0, 0, qr_width, qr_height, left0, oy); + BSOD_PIXMAP (bst, 0, 0, qs, qs, left0, oy); } } @@ -7035,6 +7033,26 @@ systemd (Display *dpy, Window window) { struct bsod_state *bst = make_bsod_state (dpy, window, "systemd", "Systemd"); int lh = (bst->font->ascent + bst->font->descent); + int qs = qr_size; + Pixmap pixmap; + int i, y = 0; + + pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) qr_bits, + qs, qs, + bst->fg, bst->bg, bst->xgwa.depth); + { + int n = 3; + if (bst->xgwa.width > 2560 || bst->xgwa.height > 2560) + n++; /* Retina displays */ + for (i = 0; i < n; i++) + { + pixmap = double_pixmap (dpy, bst->xgwa.visual, bst->xgwa.depth, + pixmap, qs, qs); + qs *= 2; + } + } + bst->pixmap = pixmap; + BSOD_MOVETO (bst, 0, lh); BSOD_TEXT (bst, LEFT, " .--. _\n" @@ -7044,11 +7062,15 @@ systemd (Display *dpy, Window window) " (| | ) _\n" " /'\\_ _/`\\ (_)\n" " \\___)=(___/\n"); - BSOD_MOVETO (bst, 0, (bst->xgwa.height / 2) - lh); - BSOD_TEXT (bst, CENTER, - "KERNEL PANIC !\n" - "\n" - "Please reboot your computer."); + + y = (bst->xgwa.height - qs) / 2; + if (y < lh * 8) y = lh * 8; + BSOD_PIXMAP (bst, 0, 0, qs, qs, (bst->xgwa.width - qs) / 2, y); + y += qs + lh * 3; + BSOD_MOVETO (bst, 0, y); + BSOD_TEXT (bst, CENTER, "KERNEL PANIC !\n\n"); + BSOD_TEXT (bst, CENTER, "Please reboot your computer.\n\n"); + BSOD_TEXT (bst, CENTER, "Fatal exception in interrupt"); XClearWindow (dpy, window); return bst; } From 21ddbab5e84351f2182dd92147c1286ef427aae8 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:23:16 +0200 Subject: [PATCH 16/25] ? hacks/glx/glslideshow: Rewrite Probably this is one of the > Some hacks were calling glXSwapBuffers before the first call to > glXMakeCurrent; allow it. cases mentioned in the upstream changelog, but couldn't quite figure it out. Removes the credit for the 2003 rewrite from Mike Oliphant for no clear reason. --- hacks/config/glslideshow.xml | 75 +- hacks/glx/glslideshow.c | 1410 +++++++++++++++++++++++----------- hacks/glx/glslideshow.man | 100 ++- 3 files changed, 1064 insertions(+), 521 deletions(-) diff --git a/hacks/config/glslideshow.xml b/hacks/config/glslideshow.xml index ae615e8b9..b061b0318 100644 --- a/hacks/config/glslideshow.xml +++ b/hacks/config/glslideshow.xml @@ -8,36 +8,44 @@
- - - - - - - - - + + + + + + + + + + + + - - - +
+ + + +
@@ -47,9 +55,16 @@
<_description> -Loads a random sequence of images and smoothly scans and zooms around -in each, fading from pan to pan. +Displays a slideshow of images, with panning, zooming and crossfading +effects. + +When a new image is loaded, it transitions onto the screen by sliding +in from the edges, spinning or flipping. Turn off "Image Loading Animation" +to disable those effects. + +Once an image has been loaded, it is panned, zoomed and cross-faded against +itself. Turn off "Crossfade" to disable those effects. -Written by Jamie Zawinski and Mike Oliphant; 2003. +Written by Jamie Zawinski; 2003. diff --git a/hacks/glx/glslideshow.c b/hacks/glx/glslideshow.c index 3ec34b66f..2ee1c6505 100644 --- a/hacks/glx/glslideshow.c +++ b/hacks/glx/glslideshow.c @@ -1,4 +1,4 @@ -/* glslideshow, Copyright © 2003-2022 Jamie Zawinski +/* glslideshow, Copyright © 2003-2025 Jamie Zawinski * Loads a sequence of images and smoothly pans around them; crossfades * when loading new images. * @@ -6,6 +6,7 @@ * Rewritten by jwz, 21-Jun-2003. * Rewritten by jwz again, 6-Feb-2005. * Modified by Richard Weeks Copyright (c) 2020 + * Rewritten by jwz again, 27-Nov-2025. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -64,16 +65,16 @@ #ifdef USE_GL -# define DEF_FADE_DURATION "2" -# define DEF_PAN_DURATION "6" -# define DEF_IMAGE_DURATION "30" -# define DEF_ZOOM "75" -# define DEF_FPS_CUTOFF "5" -# define DEF_TITLES "False" -# define DEF_LETTERBOX "True" -# define DEF_DEBUG "False" -# define DEF_VERBOSE "False" -# define DEF_MIPMAP "True" +# define DEF_TRANSITION_DURATION "3" +# define DEF_FADE_DURATION "2" +# define DEF_PAN_DURATION "6" +# define DEF_IMAGE_DURATION "30" +# define DEF_ZOOM "75" +# define DEF_TITLES "False" +# define DEF_LETTERBOX "True" +# define DEF_DEBUG "False" +# define DEF_VERBOSE "False" +# define DEF_MIPMAP "True" #include "grab-ximage.h" #include "texfont.h" @@ -86,6 +87,7 @@ typedef struct { double x, y, w, h; + struct { double x, y, z; } r; } rect; typedef struct { @@ -106,12 +108,23 @@ typedef struct { typedef enum { NEW, IN, FULL, OUT, DEAD } sprite_state; +typedef enum { NONE, PANZOOM, FADE, + LEFT, RIGHT, TOP, BOTTOM, + ZOOM, FLIP, SPIN } + transition_mode; + +typedef enum { LOADING, FIRST_IN, IN_PANZOOM, MID_PANZOOM, RECENTER, + TRANSITION_OUT, TRANSITION_PANZOOM } anim_state; typedef struct { int id; /* unique number for debugging */ image *img; /* which image this animation displays */ GLfloat opacity; /* how to render it */ double start_time; /* when this animation began */ + double duration; /* How long for all 3 sprite_states */ + transition_mode transition; /* how to render it */ + easing_function easing; + GLfloat zoom; /* randomized version of --zoom arg */ rect from, to, current; /* the journey this image is taking */ sprite_state state; /* the state we're in right now */ sprite_state prev_state; /* the state we were in previously */ @@ -122,18 +135,20 @@ typedef struct { typedef struct { GLXContext *glx_context; + int nimages; /* how many images are loaded or loading now */ image *images[10]; /* pointers to the images */ int nsprites; /* how many sprites are animating right now */ sprite *sprites[10]; /* pointers to the live sprites */ + anim_state state; + double now; /* current time in seconds */ double dawn_of_time; /* when the program launched */ - double image_load_time; /* time when we last loaded a new image */ - double prev_frame_time; /* time when we last drew a frame */ + double start_time; /* when we began displaying this image */ + double prev_frame_time; /* when we last drew a frame */ - Bool awaiting_first_image_p; /* Early in startup: nothing to display yet */ Bool redisplay_needed_p; /* Sometimes we can get away with not re-painting. Tick this if a redisplay is required. */ @@ -159,32 +174,33 @@ static slideshow_state *sss = NULL; /* Command-line arguments */ -static int fade_seconds; /* Duration in seconds of fade transitions. - If 0, jump-cut instead of fading. */ -static int pan_seconds; /* Duration of each pan through an image. */ -static int image_seconds; /* How many seconds until loading a new image. */ -static int zoom; /* How far in to zoom when panning, in percent of - image size: that is, 75 means "when zoomed all - the way in, 75% of the image will be visible." - */ -static int fps_cutoff; /* If the frame-rate falls below this, turn off - zooming.*/ -static Bool letterbox_p; /* When a loaded image is not the same aspect - ratio as the window, whether to display black - bars. - */ -static Bool mipmap_p; /* Use mipmaps instead of single textures. */ -static Bool do_titles; /* Display image titles. */ -static Bool verbose_p; /* Print to stderr. */ -static Bool debug_p; /* Show image extents with boxes. */ +static int transition_seconds; /* Duration in seconds of in/out transitions. + If 0, jump-cut instead of fading. */ +static int fade_seconds; /* Duration in seconds of pan-zoom transitions. + If 0, jump-cut instead of fading. */ +static int pan_seconds; /* Duration of each pan-zoom. */ +static int image_seconds; /* How long until loading a new image. */ +static int zoom; /* How far in to zoom, in percent of image + size: that is, 75 means "when zoomed all + the way in, 75% of the image will be + visible." + */ +static Bool letterbox_p; /* When a loaded image is not the same aspect + ratio as the window, whether to display + black bars. + */ +static Bool mipmap_p; /* Use mipmaps instead of single textures. */ +static Bool do_titles; /* Display image titles. */ +static Bool verbose_p; /* Print to stderr. */ +static Bool debug_p; /* Show image extents with boxes. */ static XrmOptionDescRec opts[] = { + {"-transition", ".transitionDuration", XrmoptionSepArg, 0 }, {"-fade", ".fadeDuration", XrmoptionSepArg, 0 }, {"-pan", ".panDuration", XrmoptionSepArg, 0 }, {"-duration", ".imageDuration", XrmoptionSepArg, 0 }, {"-zoom", ".zoom", XrmoptionSepArg, 0 }, - {"-cutoff", ".FPScutoff", XrmoptionSepArg, 0 }, {"-titles", ".titles", XrmoptionNoArg, "True" }, {"-letterbox", ".letterbox", XrmoptionNoArg, "True" }, {"-no-letterbox", ".letterbox", XrmoptionNoArg, "False" }, @@ -197,19 +213,21 @@ static XrmOptionDescRec opts[] = { }; static argtype vars[] = { + { &transition_seconds, "transitionDuration", "TransitionDuration", + DEF_TRANSITION_DURATION, t_Int}, { &fade_seconds, "fadeDuration", "FadeDuration", DEF_FADE_DURATION, t_Int}, { &pan_seconds, "panDuration", "PanDuration", DEF_PAN_DURATION, t_Int}, { &image_seconds, "imageDuration","ImageDuration",DEF_IMAGE_DURATION, t_Int}, { &zoom, "zoom", "Zoom", DEF_ZOOM, t_Int}, { &mipmap_p, "mipmap", "Mipmap", DEF_MIPMAP, t_Bool}, { &letterbox_p, "letterbox", "Letterbox", DEF_LETTERBOX, t_Bool}, - { &fps_cutoff, "FPScutoff", "FPSCutoff", DEF_FPS_CUTOFF, t_Int}, { &verbose_p, "verbose", "Verbose", DEF_VERBOSE, t_Bool}, { &debug_p, "debug", "Debug", DEF_DEBUG, t_Bool}, { &do_titles, "titles", "Titles", DEF_TITLES, t_Bool}, }; -ENTRYPOINT ModeSpecOpt slideshow_opts = {countof(opts), opts, countof(vars), vars, NULL}; +ENTRYPOINT ModeSpecOpt slideshow_opts = { + countof(opts), opts, countof(vars), vars, NULL}; static const char * @@ -239,38 +257,6 @@ static void image_loaded_cb (const char *filename, XRectangle *geom, void *closure); -/* Allocate an image structure and start a file loading in the background. - */ -static image * -alloc_image (ModeInfo *mi) -{ - slideshow_state *ss = &sss[MI_SCREEN(mi)]; - int wire = MI_IS_WIREFRAME(mi); - image *img = (image *) calloc (1, sizeof (*img)); - - img->id = ++ss->image_id; - img->loaded_p = False; - img->used_p = False; - img->mi = mi; - - glGenTextures (1, &img->texid); - if (img->texid <= 0) abort(); - - ss->image_load_time = ss->now; - - if (wire) - image_loaded_cb (0, 0, 0, 0, 0, 0, img); - else - load_texture_async (mi->xgwa.screen, mi->window, *ss->glx_context, - 0, 0, mipmap_p, img->texid, image_loaded_cb, img); - - ss->images[ss->nimages++] = img; - if (ss->nimages >= countof(ss->images)) abort(); - - return img; -} - - /* Allocate an image structure and start asynchronous file loading in the background. @@ -294,8 +280,6 @@ alloc_image_incremental (ModeInfo *mi) glGenTextures (1, &img->texid); if (img->texid <= 0) abort(); - ss->image_load_time = ss->now; - if (wire) image_loaded_cb (0, 0, 0, 0, 0, 0, img); else @@ -310,6 +294,31 @@ alloc_image_incremental (ModeInfo *mi) } +/* Step the incremental image loader. + */ +static void +slideshow_idle (ModeInfo *mi) +{ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; + double allowed_time = ((double) mi->pause) / 2000000; /* 0.01 sec */ + int i; + + for (i = 0; i < ss->nimages; i++) + { + image *img = ss->images[i]; + if (img->loader) + { + if (texture_loader_failed (img->loader)) + abort(); + step_texture_loader (img->loader, allowed_time, + image_loaded_cb, img); + img->steps++; + break; /* only do the first one! */ + } + } +} + + /* Callback that tells us that the texture has been loaded. */ static void @@ -430,6 +439,13 @@ destroy_image (ModeInfo *mi, image *img) fprintf (stderr, "%s: unloaded img %2d: \"%s\"\n", blurb(), img->id, (img->title ? img->title : "(null)")); + if (img->loader) + { + texture_loader_t *loader = img->loader; + img->loader = 0; + free_texture_loader (loader); + } + if (img->title) free (img->title); glDeleteTextures (1, &img->texid); free (img); @@ -437,18 +453,14 @@ destroy_image (ModeInfo *mi, image *img) /* Return an image to use for a sprite. - If it's time for a new one, get a new one. - Otherwise, use an old one. - Might return 0 if the machine is really slow. + Might return 0 if a new image is unavailable because + the machine is being really slow. */ static image * -get_image (ModeInfo *mi) +get_image (ModeInfo *mi, Bool want_new_p) { slideshow_state *ss = &sss[MI_SCREEN(mi)]; - image *img = 0; - double now = ss->now; - Bool want_new_p = (ss->change_now_p || - ss->image_load_time + image_seconds <= now); + image *ret = 0; image *new_img = 0; image *old_img = 0; image *loading_img = 0; @@ -466,121 +478,25 @@ get_image (ModeInfo *mi) old_img = img2; } - if (want_new_p && new_img) - img = new_img, new_img = 0, ss->change_now_p = False; - else if (old_img) - img = old_img, old_img = 0; - else if (new_img) - img = new_img, new_img = 0, ss->change_now_p = False; + /* If a new image was requested but unavailable, return NULL. */ + ret = want_new_p ? new_img : old_img; - /* Make sure that there is always one unused image in the pipe. - */ + /* Make sure that there is always one unused image in the pipe. */ if (!new_img && !loading_img) alloc_image_incremental (mi); - return img; -} - - -/* Pick random starting and ending positions for the given sprite. - */ -static void -randomize_sprite (ModeInfo *mi, sprite *sp) -{ - int vp_w = MI_WIDTH(mi); - int vp_h = MI_HEIGHT(mi); - int img_w = sp->img->geom.width; - int img_h = sp->img->geom.height; - int min_w, max_w; - double ratio = (double) img_h / img_w; - - if (letterbox_p) - { - min_w = img_w; - } - else - { - if (img_w < vp_w) - min_w = vp_w; - else - min_w = img_w * (float) vp_h / img_h; - } - - max_w = min_w * 100 / zoom; - - sp->from.w = min_w + frand ((max_w - min_w) * 0.4); - sp->to.w = max_w - frand ((max_w - min_w) * 0.4); - sp->from.h = sp->from.w * ratio; - sp->to.h = sp->to.w * ratio; - - if (zoom == 100) /* only one box, and it is centered */ - { - sp->from.x = (sp->from.w > vp_w - ? -(sp->from.w - vp_w) / 2 - : (vp_w - sp->from.w) / 2); - sp->from.y = (sp->from.h > vp_h - ? -(sp->from.h - vp_h) / 2 - : (vp_h - sp->from.h) / 2); - sp->to = sp->from; - } - else /* position both boxes randomly */ - { - sp->from.x = (sp->from.w > vp_w - ? -frand (sp->from.w - vp_w) - : frand (vp_w - sp->from.w)); - sp->from.y = (sp->from.h > vp_h - ? -frand (sp->from.h - vp_h) - : frand (vp_h - sp->from.h)); - sp->to.x = (sp->to.w > vp_w - ? -frand (sp->to.w - vp_w) - : frand (vp_w - sp->to.w)); - sp->to.y = (sp->to.h > vp_h - ? -frand (sp->to.h - vp_h) - : frand (vp_h - sp->to.h)); - } - - if (random() & 1) - { - rect swap = sp->to; - sp->to = sp->from; - sp->from = swap; - } - - /* Make sure the aspect ratios are within 0.001 of each other. - */ - { - int r1 = 0.5 + (sp->from.w * 1000 / sp->from.h); - int r2 = 0.5 + (sp->to.w * 1000 / sp->to.h); - if (r1 < r2-1 || r1 > r2+1) - { - fprintf (stderr, - "%s: botched aspect: %f x %f (%d) vs %f x %f (%d): %s\n", - progname, - sp->from.w, sp->from.h, r1, - sp->to.w, sp->to.h, r2, - (sp->img->title ? sp->img->title : "[null]")); - abort(); - } - } - - sp->from.x /= vp_w; - sp->from.y /= vp_h; - sp->from.w /= vp_w; - sp->from.h /= vp_h; - sp->to.x /= vp_w; - sp->to.y /= vp_h; - sp->to.w /= vp_w; - sp->to.h /= vp_h; + return ret; } /* Allocate a new sprite and start its animation going. + Returns 0 if no images available yet. */ static sprite * -new_sprite (ModeInfo *mi) +new_sprite (ModeInfo *mi, Bool want_new_p) { slideshow_state *ss = &sss[MI_SCREEN(mi)]; - image *img = get_image (mi); + image *img = get_image (mi, want_new_p); sprite *sp; if (!img) @@ -591,20 +507,30 @@ new_sprite (ModeInfo *mi) return 0; } + if (!img->loaded_p) abort(); + sp = (sprite *) calloc (1, sizeof (*sp)); sp->id = ++ss->sprite_id; sp->start_time = ss->now; sp->state_time = sp->start_time; sp->state = sp->prev_state = NEW; + sp->zoom = (zoom + ? 1 + frand ((100.0 / zoom) - 1) /* 75% => [1.0 - 1.33] */ + : 1); sp->img = img; sp->img->refcount++; sp->img->used_p = True; + if (want_new_p) + ss->start_time = ss->now; + ss->sprites[ss->nsprites++] = sp; if (ss->nsprites >= countof(ss->sprites)) abort(); - randomize_sprite (mi, sp); + if (verbose_p) + fprintf (stderr, "%s: new sprite %d, img %d\n", blurb(), sp->id, + sp->img->id); return sp; } @@ -623,10 +549,13 @@ destroy_sprite (ModeInfo *mi, sprite *sp) if (!sp) abort(); if (sp->state != DEAD) abort(); img = sp->img; - if (!img) abort(); - if (!img->loaded_p) abort(); - if (!img->used_p) abort(); - if (img->refcount <= 0) abort(); + /* if (!img) abort(); */ + if (img) + { + if (!img->loaded_p) abort(); + if (!img->used_p) abort(); + if (img->refcount <= 0) abort(); + } for (i = 0; i < ss->nsprites; i++) /* unlink it from the list */ if (ss->sprites[i] == sp) @@ -641,114 +570,412 @@ destroy_sprite (ModeInfo *mi, sprite *sp) } if (!freed_p) abort(); + + if (verbose_p) + fprintf (stderr, "%s: free sprite %d\n", blurb(), sp->id); + free (sp); sp = 0; - img->refcount--; - if (img->refcount < 0) abort(); - if (img->refcount == 0) - destroy_image (mi, img); + if (img) + { + img->refcount--; + if (img->refcount < 0) abort(); + if (img->refcount == 0) + destroy_image (mi, img); + } } -/* Updates the sprite for the current frame of the animation based on - its creation time compared to the current wall clock. - */ static void -tick_sprite (ModeInfo *mi, sprite *sp) +launch_sprite (ModeInfo *mi) { slideshow_state *ss = &sss[MI_SCREEN(mi)]; - image *img = sp->img; - double now = ss->now; - double secs; - double ratio; - rect prev_rect = sp->current; - GLfloat prev_opacity = sp->opacity; - - if (! sp->img) abort(); - if (! img->loaded_p) abort(); - - secs = now - sp->start_time; - ratio = secs / (pan_seconds + fade_seconds); - if (ratio > 1) ratio = 1; - - sp->current.x = sp->from.x + ratio * (sp->to.x - sp->from.x); - sp->current.y = sp->from.y + ratio * (sp->to.y - sp->from.y); - sp->current.w = sp->from.w + ratio * (sp->to.w - sp->from.w); - sp->current.h = sp->from.h + ratio * (sp->to.h - sp->from.h); + int vp_w = MI_WIDTH(mi); + int vp_h = MI_HEIGHT(mi); + sprite *out, *in; + sprite *sprites[2]; + int sprite_w[countof(sprites)]; + int sprite_max_w = 0; + int sprite_max_h = 0; + int i; - sp->prev_state = sp->state; + if (ss->state == LOADING) + return; - if (secs < fade_seconds) - { - sp->state = IN; - sp->opacity = secs / (GLfloat) fade_seconds; - } - else if (secs < pan_seconds) + if (ss->state == FIRST_IN) + out = NULL; + else if (ss->nsprites > 0) + out = ss->sprites[ss->nsprites-1]; + else { - sp->state = FULL; - sp->opacity = 1; + fprintf (stderr, "%s: no out sprite\n", blurb()); + abort(); } - else if (secs < pan_seconds + fade_seconds) + + in = new_sprite (mi, (ss->state == FIRST_IN || + ss->state == TRANSITION_OUT || + ss->state == TRANSITION_PANZOOM)); + if (!in) { - sp->state = OUT; - sp->opacity = 1 - ((secs - pan_seconds) / (GLfloat) fade_seconds); + fprintf (stderr, "%s: no in sprite\n", blurb()); + abort(); } - else + + sprites[0] = out; + sprites[1] = in; + + switch (ss->state) { + case FIRST_IN: + case TRANSITION_OUT: + + /* Compute the maximal extents of the pair, including letterboxing. + For the overlapping horizontal/vertical transitions to look right, + the two sprites have to transit the same distance, not just 100%. + */ + sprite_max_w = vp_w; + sprite_max_h = vp_h; + + for (i = 0; i < countof(sprites); i++) + { + sprite *sp = sprites[i]; + int w, h; + double ratio; + if (!sp) continue; + ratio = (double) sp->img->geom.height / sp->img->geom.width; + + if (letterbox_p) + { + if (vp_w * ratio < vp_h) + w = vp_w; /* full width, smaller height */ + else + w = vp_h / ratio; /* full height, smaller width */ + } + else + { + if (vp_w * ratio < vp_h) + w = vp_h / ratio; /* full height, crop width */ + else + w = vp_w; /* full width, crop height */ + } + + w *= sp->zoom; + + sprite_w[i] = w; + h = w * ratio; + if (w > sprite_max_w) sprite_max_w = w; + if (h > sprite_max_h) sprite_max_h = h; + } + { - sp->state = DEAD; - sp->opacity = 0; + const transition_mode mm[] = { + FADE, LEFT, RIGHT, TOP, BOTTOM, FLIP, SPIN + }; + const easing_function ee[] = { + EASE_IN_OUT_QUAD, EASE_IN_OUT_QUAD, EASE_IN_OUT_QUAD, EASE_IN_OUT_QUAD, + EASE_IN_OUT_QUINT, EASE_IN_OUT_QUINT, + EASE_IN_OUT_BACK, EASE_IN_OUT_BACK, + EASE_IN_CUBIC, EASE_IN_CUBIC, + }; + transition_mode t; + easing_function e; + t = mm[random() % countof(mm)]; + e = ee[random() % countof(ee)]; + + if (ss->state == FIRST_IN && out) abort(); + if (ss->state == TRANSITION_OUT && !out) abort(); + + for (i = 0; i < countof(sprites); i++) + { + Bool out_p = (i == 0); + sprite *sp = sprites[i]; + double ratio; + if (!sp) continue; + + sp->state = out_p ? OUT : IN; + sp->start_time = ss->now; + sp->duration = transition_seconds; + + if (!out_p && pan_seconds <= 0) + /* If we are not doing PANZOOM, then this image will + linger on screen for the full image duration. */ + sp->duration += image_seconds; + + ratio = (double) sp->img->geom.height / sp->img->geom.width; + + /* Default coordinates are centered. */ + sp->to.w = sprite_w[i]; + sp->to.h = sp->to.w * ratio; + sp->to.x = (sp->to.w > vp_w + ? -(sp->to.w - vp_w) / 2 + : (vp_w - sp->to.w) / 2); + sp->to.y = (sp->to.h > vp_h + ? -(sp->to.h - vp_h) / 2 + : (vp_h - sp->to.h) / 2); + sp->to.r.x = 0; + sp->to.r.y = 0; + sp->to.r.z = 0; + sp->from = sp->to; + + sp->transition = t; + sp->easing = e; + + switch (t) { + case FADE: + /* No motion, only alpha */ + break; + + case LEFT: + if (out_p) + sp->to.x = sp->to.x + sprite_max_w; + else + sp->from.x = sp->to.x - sprite_max_w; + break; + + case RIGHT: + if (out_p) + sp->to.x = sp->to.x - sprite_max_w; + else + sp->from.x = sp->to.x + sprite_max_w; + break; + + case TOP: + if (out_p) + sp->to.y = sp->to.y - sprite_max_h; + else + sp->from.y = sp->to.y + sprite_max_h; + break; + + case BOTTOM: + if (out_p) + sp->to.y = sp->to.y + sprite_max_h; + else + sp->from.y = sp->to.y - sprite_max_h; + break; + + case ZOOM: + if (out_p) + { + sp->to.x = vp_w / 2; + sp->to.y = vp_h / 2; + sp->to.w = 1; + sp->to.h = sp->to.w * ratio; + } + else + { + sp->from.x = vp_w / 2; + sp->from.y = vp_h / 2; + sp->from.w = 1; + sp->from.h = sp->from.w * ratio; + } + break; + + case SPIN: + { + int quads = 2 + (random() % 6); + GLfloat spin = (!out_p && out + ? -out->to.r.z + : (90 * quads * + (random() & 1 ? 1 : -1))); + GLfloat scale = 0.0001; + if (out_p) + { + sp->to.r.z = spin; + sp->to.w *= scale; + sp->to.h *= scale; + sp->to.x = (vp_w - sp->to.w) / 2; + sp->to.y = (vp_h - sp->to.h) / 2; + } + else + { + sp->from.r.z = spin; + sp->from.w *= scale; + sp->from.h *= scale; + sp->from.x = (vp_w - sp->from.w) / 2; + sp->from.y = (vp_h - sp->from.h) / 2; + } + } + break; + + case FLIP: + { + Bool horiz_p = random() & 1; + Bool sign = (random() & 1 ? 1 : -1); + GLfloat flipx = (!out_p && out + ? -out->to.r.x + : horiz_p ? 180 * sign : 0); + GLfloat flipy = (!out_p && out + ? -out->to.r.y + : horiz_p ? 0 : 180 * sign); + if (out_p) + { + sp->to.r.x = flipx; + sp->to.r.y = flipy; + } + else + { + sp->from.r.x = flipx; + sp->from.r.y = flipy; + } + } + break; + + default: + abort(); + break; + } + } + + if (out && verbose_p) + fprintf (stderr, "%s: adjust TR sprite %d dur %.1f start %.1f\n", + blurb(), out->id, out->duration, + out->start_time - ss->now); } + break; + + case IN_PANZOOM: + /* Adjust the just-transitioned-in image to fade out, as the + second sprite starts fading in. + */ + if (!out) abort(); + out->duration = pan_seconds; + out->duration = fade_seconds + pan_seconds; + out->start_time = ss->now - pan_seconds; + out->transition = PANZOOM; + out->state = FULL; + out->prev_state = OUT; + out->to = out->current; + out->from = out->current; + + if (verbose_p) + fprintf (stderr, "%s: adjust PZ sprite %d dur %.1f start %.1f\n", + blurb(), out->id, out->duration, + out->start_time - ss->now); + + /* fallthrough */ + + case MID_PANZOOM: + case RECENTER: + case TRANSITION_PANZOOM: + if (!in) abort(); + in->duration = fade_seconds + pan_seconds; + in->start_time = ss->now; + in->transition = PANZOOM; + in->state = IN; - if (sp->state != sp->prev_state && - (sp->prev_state == IN || - sp->prev_state == FULL)) { - double secs = now - sp->state_time; + int w; + double ratio = (double) in->img->geom.height / in->img->geom.width; + double in_zoom[2]; + + if (letterbox_p) + { + if (vp_w * ratio < vp_h) + w = vp_w; /* full width, smaller height */ + else + w = vp_h / ratio; /* full height, smaller width */ + } + else + { + if (vp_w * ratio < vp_h) + w = vp_h / ratio; /* full height, crop width */ + else + w = vp_w; /* full width, crop height */ + } + + in_zoom[0] = (zoom + ? 1 + frand ((100.0 / zoom) - 1) /* 75% => [1.0 - 1.33] */ + : 1); + in_zoom[1] = (zoom + ? 1 + frand ((100.0 / zoom) - 1) + : 1); + + if (ss->state == RECENTER) + in_zoom[1] = in->zoom; + + in->from.w = w * in_zoom[0]; + in->from.h = in->from.w * ratio; + in->from.r.x = 0; + in->from.r.y = 0; + in->from.r.z = 0; + + in->from.x = (in->from.w > vp_w + ? -frand (in->from.w - vp_w) + : frand (vp_w - in->from.w)); + in->from.y = (in->from.h > vp_h + ? -frand (in->from.h - vp_h) + : frand (vp_h - in->from.h)); + + in->to.w = w * in_zoom[1]; + in->to.h = in->to.w * ratio; + in->to.r.x = 0; + in->to.r.y = 0; + in->to.r.z = 0; + + if (ss->state == RECENTER) + { + in->to.x = (in->to.w > vp_w + ? -(in->to.w - vp_w) / 2 + : (vp_w - in->to.w) / 2); + in->to.y = (in->to.h > vp_h + ? -(in->to.h - vp_h) / 2 + : (vp_h - in->to.h) / 2); + } + else + { + in->to.x = (in->to.w > vp_w + ? -frand (in->to.w - vp_w) + : frand (vp_w - in->to.w)); + in->to.y = (in->to.h > vp_h + ? -frand (in->to.h - vp_h) + : frand (vp_h - in->to.h)); + } - if (verbose_p) - fprintf (stderr, - "%s: %s %3d frames %2.0f sec %5.1f fps (max %.1f fps?)\n", - blurb(), - (sp->prev_state == IN ? "fade" : "pan "), - sp->frame_count, - secs, - sp->frame_count / secs, - ss->theoretical_fps); - - sp->state_time = now; - sp->frame_count = 0; } + break; - sp->frame_count++; + default: + abort(); + break; + } - if (sp->state != DEAD && - (prev_rect.x != sp->current.x || - prev_rect.y != sp->current.y || - prev_rect.w != sp->current.w || - prev_rect.h != sp->current.h || - prev_opacity != sp->opacity)) - ss->redisplay_needed_p = True; + if (verbose_p) + fprintf (stderr, "%s: launch sprite %d dur %.1f\n", + blurb(), in->id, in->duration); } + /* Draw the given sprite at the phase of its animation dictated by its creation time compared to the current wall clock. */ static void -draw_sprite (ModeInfo *mi, sprite *sp, Bool keep_title_p) +draw_sprite (ModeInfo *mi, sprite *sp) { - slideshow_state *ss = &sss[MI_SCREEN(mi)]; + /* slideshow_state *ss = &sss[MI_SCREEN(mi)]; */ int wire = MI_IS_WIREFRAME(mi); image *img = sp->img; + int vp_w = MI_WIDTH(mi); + int vp_h = MI_HEIGHT(mi); if (! sp->img) abort(); if (! img->loaded_p) abort(); glPushMatrix(); { - glTranslatef (sp->current.x, sp->current.y, 0); - glScalef (sp->current.w, sp->current.h, 1); + GLfloat aspect = vp_w / (GLfloat) vp_h; + glScalef (1, aspect, 1); + glRotatef (sp->current.r.x, 1, 0, 0); + glRotatef (sp->current.r.y, 0, 1, 0); + glRotatef (sp->current.r.z, 0, 0, 1); + glScalef (1, 1/aspect, 1); + + glTranslatef (sp->current.x / vp_w - 0.5, + sp->current.y / vp_h - 0.5, + 0); + glScalef (sp->current.w / vp_w, + sp->current.h / vp_h, + 1); if (wire) /* Draw a grid inside the box */ { @@ -822,20 +1049,11 @@ draw_sprite (ModeInfo *mi, sprite *sp, Bool keep_title_p) if (!wire) glEnable (GL_TEXTURE_2D); } } - - - if (do_titles && img->title && *img->title) - { - glColor4f (1, 1, 1, keep_title_p ? 1 : sp->opacity); - print_texture_label (mi->dpy, ss->font_data, - mi->xgwa.width, mi->xgwa.height, - 1, img->title); - } } - glPopMatrix(); if (debug_p) { +#if 1 if (!wire) glDisable (GL_TEXTURE_2D); if (sp->id & 1) @@ -860,7 +1078,10 @@ draw_sprite (ModeInfo *mi, sprite *sp, Bool keep_title_p) glEnd(); if (!wire) glEnable (GL_TEXTURE_2D); +#endif } + + glPopMatrix(); } @@ -868,9 +1089,312 @@ static void tick_sprites (ModeInfo *mi) { slideshow_state *ss = &sss[MI_SCREEN(mi)]; + anim_state ostate = ss->state; + double total_secs = ss->now - ss->start_time; + sprite *sp = ss->nsprites > 0 ? ss->sprites[ss->nsprites-1] : NULL; + double sp_secs = sp ? ss->now - sp->start_time : 0; + Bool launch_p = FALSE; + Bool image_p; int i; + + /* Make sure that there is always one unused image in the pipe. */ + get_image (mi, TRUE); + + image_p = (ss->nimages > 0 && + ss->images[ss->nimages-1]->loaded_p && + !ss->images[ss->nimages-1]->used_p); + + switch (ss->state) { + + case LOADING: + if (image_p) + ss->state = FIRST_IN; + ss->redisplay_needed_p = TRUE; + break; + + case FIRST_IN: + case TRANSITION_OUT: + if (!sp && ss->state == TRANSITION_OUT) + { + fprintf (stderr, "%s: no TRANSITION_OUT sprite\n", blurb()); + abort(); + } + else if (ss->change_now_p && image_p) + { + ss->state = TRANSITION_OUT; + launch_p = TRUE; + } + else if (total_secs >= transition_seconds && pan_seconds) + ss->state = IN_PANZOOM; + else if (total_secs >= image_seconds && image_p) + { + ss->state = TRANSITION_OUT; + launch_p = TRUE; /* do TRANSITION_OUT again */ + } + break; + + case IN_PANZOOM: + if (!sp) + { + fprintf (stderr, "%s: no IN_PANZOOM sprite\n", blurb()); + abort(); + } + else if (ss->change_now_p && image_p) + { + if (transition_seconds <= 0) + ss->state = TRANSITION_PANZOOM; + else + ss->state = RECENTER; + } + else if (sp_secs >= pan_seconds) + ss->state = MID_PANZOOM; + break; + + case MID_PANZOOM: + case TRANSITION_PANZOOM: + if (!sp) + { + fprintf (stderr, "%s: no MID_PANZOOM sprite\n", blurb()); + abort(); + } + else if (image_p && + (ss->change_now_p || + sp_secs >= pan_seconds)) + { + if ((ss->change_now_p && image_p) || + total_secs >= image_seconds - (fade_seconds + pan_seconds)) + { + if (transition_seconds <= 0) + { + /* TRANSITION_PANZOOM is just like MID_PANZOOM but loads + a new image instead of reusing an old one. */ + ss->state = TRANSITION_PANZOOM; + launch_p = TRUE; + } + else + { + ss->state = RECENTER; + } + } + else + { + ss->state = MID_PANZOOM; + launch_p = TRUE; + } + } + break; + + case RECENTER: + if (!sp) + { + fprintf (stderr, "%s: no RECENTER sprite\n", blurb()); + abort(); + } + else if (sp_secs >= pan_seconds + fade_seconds && + total_secs >= image_seconds) + ss->state = TRANSITION_OUT; + break; + + default: + abort(); + break; + } + + ss->change_now_p = FALSE; + for (i = 0; i < ss->nsprites; i++) - tick_sprite (mi, ss->sprites[i]); + { + sprite *sp = ss->sprites[i]; + sp_secs = ss->now - sp->start_time; + } + + if (ostate != ss->state) launch_p = TRUE; + + if (launch_p) + { + if (verbose_p) + fprintf (stderr, "%s: %s => %s\n", blurb(), + (ostate == LOADING ? "LOADING" : + ostate == FIRST_IN ? "FIRST_IN" : + ostate == IN_PANZOOM ? "IN_PANZOOM" : + ostate == MID_PANZOOM ? "MID_PANZOOM" : + ostate == RECENTER ? "RECENTER" : + ostate == TRANSITION_OUT ? "TRANSITION_OUT" : "???"), + (ss->state == LOADING ? "LOADING" : + ss->state == FIRST_IN ? "FIRST_IN" : + ss->state == IN_PANZOOM ? "IN_PANZOOM" : + ss->state == MID_PANZOOM ? "MID_PANZOOM" : + ss->state == RECENTER ? "RECENTER" : + ss->state == TRANSITION_OUT ? "TRANSITION_OUT" : + ss->state == TRANSITION_PANZOOM ? "TRANSITION_PANZOOM" : + "???")); + + launch_sprite (mi); + return; + } + + for (i = 0; i < countof(ss->sprites); i++) + { + sprite *sp = ss->sprites[i]; + double ratio; + double secs; + double prev_opacity; + rect prev_rect; + if (!sp) continue; + + secs = ss->now - sp->start_time; + + sp->prev_state = sp->state; + prev_rect = sp->current; + prev_opacity = sp->opacity; + + switch (sp->transition) { + case PANZOOM: + ratio = secs / (fade_seconds + pan_seconds); + + if (secs <= fade_seconds) /* PANZOOM is 3 transitions in one */ + { + sp->opacity = secs / fade_seconds; + if (sp->opacity > 1) sp->opacity = 1; + sp->state = IN; + } + else if (secs <= pan_seconds) + { + sp->state = FULL; + sp->opacity = 1; + } + else if (secs <= fade_seconds + pan_seconds) + { + sp->opacity = 1 - ((secs - pan_seconds) / fade_seconds); + sp->state = OUT; + if (ss->state == RECENTER && + i == ss->nsprites-1) + sp->opacity = 1; + } + else + { + sp->state = DEAD; + sp->opacity = 0; + } + break; + + case LEFT: + case RIGHT: + case TOP: + case BOTTOM: + case FLIP: + case FADE: + case ZOOM: + case SPIN: + ratio = secs / transition_seconds; + if (ratio <= 1) + { + if (sp->transition == FADE || + sp->transition == ZOOM || + sp->transition == SPIN) + sp->opacity = (sp->state == IN ? ratio : 1-ratio); + else + sp->opacity = 1; + } + else if (secs <= sp->duration) + { + ratio = 1; /* Linger */ + sp->opacity = 1; + } + else + { + sp->state = DEAD; + ratio = 1; + sp->opacity = 0; + } + break; + default: + abort(); + break; + } + + ratio = ease (sp->easing, ratio); + sp->current.x = sp->from.x + ratio * (sp->to.x - sp->from.x); + sp->current.y = sp->from.y + ratio * (sp->to.y - sp->from.y); + sp->current.w = sp->from.w + ratio * (sp->to.w - sp->from.w); + sp->current.h = sp->from.h + ratio * (sp->to.h - sp->from.h); + sp->current.r.x = sp->from.r.x + ratio * (sp->to.r.x - sp->from.r.x); + sp->current.r.y = sp->from.r.y + ratio * (sp->to.r.y - sp->from.r.y); + sp->current.r.z = sp->from.r.z + ratio * (sp->to.r.z - sp->from.r.z); + + sp->frame_count++; + + if (sp->state != DEAD && + (prev_rect.x != sp->current.x || + prev_rect.y != sp->current.y || + prev_rect.w != sp->current.w || + prev_rect.h != sp->current.h || + prev_rect.r.x != sp->current.r.x || + prev_rect.r.y != sp->current.r.y || + prev_rect.r.z != sp->current.r.z || + prev_opacity != sp->opacity)) + ss->redisplay_needed_p = True; + + if (0 && verbose_p && debug_p && ss->redisplay_needed_p) + fprintf (stderr, "%s: %d: %5.0f %-5.0f %5.0f %-5.0f %.1f\n", blurb(), + sp->id, + sp->current.x, sp->current.y, + sp->current.w, sp->current.h, + sp->opacity); + + if (sp->state != sp->prev_state) + { + if (verbose_p) + fprintf (stderr, + "%s: %d: %-4s %-5s %3d frames %2.0f sec %5.1f fps" + " (max %.0f fps?)\n", + blurb(), + sp->id, + (sp->prev_state == NEW ? "NEW" : + sp->prev_state == IN ? "IN" : + sp->prev_state == FULL ? "FULL" : + sp->prev_state == OUT ? "FULL" : + sp->prev_state == DEAD ? "DEAD" : "???"), + (sp->transition == NONE ? "NONE" : + sp->transition == PANZOOM ? "PZ" : + sp->transition == FADE ? "FADE" : + sp->transition == LEFT ? "LEFT" : + sp->transition == RIGHT ? "RIGHT" : + sp->transition == TOP ? "TOP" : + sp->transition == BOTTOM ? "BOT" : + sp->transition == ZOOM ? "ZOOM" : + sp->transition == FLIP ? "FLIP" : + sp->transition == SPIN ? "SPIN" : "???"), + sp->frame_count, + secs, + sp->frame_count / secs, + ss->theoretical_fps); + sp->state_time = ss->now; + sp->frame_count = 0; + } + } + + for (i = 0; i < ss->nsprites; i++) + { + sprite *sp = ss->sprites[i]; + if (sp->state == DEAD) + { + /* Don't unload the last sprite if we are stalled waiting for an + image to load. */ + if (ss->nsprites < 2 && !image_p) + continue; + destroy_sprite (mi, sp); + i--; + } + } + + if (ss->nsprites > 3 || + ss->nsprites > countof (ss->sprites) || + ss->nsprites < (!image_p ? 0 : 1)) + { + fprintf (stderr, "%s: %d sprites\n", blurb(), ss->nsprites); + abort(); + } } @@ -878,40 +1402,58 @@ static void draw_sprites (ModeInfo *mi) { slideshow_state *ss = &sss[MI_SCREEN(mi)]; - char *last_title = 0; int i; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glPushMatrix(); -/* - { - GLfloat rot = current_device_rotation(); - glTranslatef (0.5, 0.5, 0); - glRotatef(rot, 0, 0, 1); - if ((rot > 45 && rot < 135) || - (rot < -45 && rot > -135)) - { - GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi); - glScalef (s, 1/s, 1); - } - glTranslatef (-0.5, -0.5, 0); - } -*/ + if (debug_p) + { + GLfloat s = 0.75; + glScalef (s, s, s); + } + + if (ss->state == LOADING) + { + double secs = ss->now - ss->dawn_of_time; + double opacity = secs / 6; + if (opacity > 1) opacity = 1; + glColor4f (1, 1, 0, opacity); + print_texture_label (mi->dpy, ss->font_data, + mi->xgwa.width, mi->xgwa.height, + 0, "Loading..."); + } for (i = 0; i < ss->nsprites; i++) + draw_sprite (mi, ss->sprites[i]); + + if (do_titles) { - sprite *s = ss->sprites[i]; - /* If the two sprites have the same title, draw the second title at - full intensity to avoid a weird blooming effect when crossfading - an image with itself. */ - Bool keep_title_p = (do_titles && last_title && s->img->title && - !strcmp (last_title, s->img->title)); - draw_sprite (mi, s, keep_title_p); - last_title = s->img->title; + sprite *sp = (ss->nsprites > 0 + ? ss->sprites[ss->nsprites-1] + : 0); + if (sp && sp->img && sp->img->loaded_p && + sp->img->title && *sp->img->title) + { + double start = (transition_seconds + ? transition_seconds : fade_seconds); + double end = (image_seconds - + (transition_seconds ? 0 : pan_seconds)); + double secs = ss->now - ss->start_time; + double sec_fade = 3; + GLfloat alpha = 1; + if (secs - start <= sec_fade) + alpha = (secs - start) / sec_fade; + else if (secs + sec_fade >= end) + alpha = (end - secs) / sec_fade; + if (alpha < 0) alpha = 0; + if (alpha > 1) alpha = 1; + glColor4f (1, 1, 1, alpha); + print_texture_label (mi->dpy, ss->font_data, + mi->xgwa.width, mi->xgwa.height, + 1, sp->img->title); + } } - glPopMatrix(); if (debug_p) /* draw a white box (the "screen") */ { @@ -921,14 +1463,23 @@ draw_sprites (ModeInfo *mi) glColor4f (1, 1, 1, 1); glBegin (GL_LINE_LOOP); - glVertex3f (0, 0, 0); - glVertex3f (0, 1, 0); - glVertex3f (1, 1, 0); - glVertex3f (1, 0, 0); + glVertex3f (-0.5, -0.5, 0); + glVertex3f (-0.5, 0.5, 0); + glVertex3f ( 0.5, 0.5, 0); + glVertex3f ( 0.5, -0.5, 0); + glEnd(); + + glBegin (GL_LINES); + glVertex3f (-0.05, 0, 0); + glVertex3f ( 0.05, 0, 0); + glVertex3f (0, -0.05, 0); + glVertex3f (0, 0.05, 0); glEnd(); if (!wire) glEnable (GL_TEXTURE_2D); } + + glPopMatrix(); } @@ -936,27 +1487,31 @@ ENTRYPOINT void reshape_slideshow (ModeInfo *mi, int width, int height) { slideshow_state *ss = &sss[MI_SCREEN(mi)]; - GLfloat s; + + /* Empirically, these numbers give us a projection where a 1x1 quad + centered at 0,0,0 fills the viewport 100%, while still having a + non-ortho projection. All 3 numbers are interdependent. + Presumably 'scale' could be computed from the others, somehow... + */ + GLfloat fov = 30; + GLfloat cam = 15; + GLfloat scale = 8.03845; + glViewport (0, 0, width, height); glMatrixMode (GL_PROJECTION); glLoadIdentity(); + gluPerspective (fov, 1, 0.01, 100); + glRotatef (current_device_rotation(), 0, 0, 1); glMatrixMode (GL_MODELVIEW); glLoadIdentity(); - s = 2; - - if (debug_p) - { - s *= (zoom / 100.0) * 0.75; - if (s < 0.1) s = 0.1; - } - - glScalef (s, s, s); - glTranslatef (-0.5, -0.5, 0); + gluLookAt (0, 0, cam, + 0, 0, 0, + 0, 1, 0); + glScalef (scale, scale, scale); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - ss->redisplay_needed_p = True; } @@ -975,11 +1530,14 @@ slideshow_handle_event (ModeInfo *mi, XEvent *event) fprintf (stderr, "%s: exposure\n", blurb()); return False; } +#if 0 /* This tends to trigger "no sprites" aborts, and I don't care + enough to debug it. */ else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) { ss->change_now_p = True; return True; } +#endif return False; } @@ -991,42 +1549,73 @@ slideshow_handle_event (ModeInfo *mi, XEvent *event) static void sanity_check (ModeInfo *mi) { + /* When transitioning one image out and another in (e.g., + one image slides out to the right while a new one slides + in from the left) the two sprites run simultaneously over + 'transition' seconds. + + After an image has transitioned in and is centered on screen, + we begin the PANZOOM phase, in which each sprite has three + states: fading in, full, fading out. The in/out states + overlap like this: + + iiiiiiFFFFFFFFFFFFoooooo . . . . . . . . . . . . . . . . . + . . . . . . . . . iiiiiiFFFFFFFFFFFFoooooo . . . . . . . . + . . . . . . . . . . . . . . . . . . iiiiiiFFFFFFFFFFFFooooo + + In PANZOOM, we create a new sprite in the IN state as soon + as the old sprite enters the OUT state. + + The "fade in + pan" phase lasts 'pan' seconds: 'fade' is + inclusive of 'pan'. So the non-overlapped part takes 'pan' + seconds but the whole animation takes 'fade + pan' seconds + (not 'pan + fade + pan' seconds). + + To avoid necessitating a jump-cut or blank screen, when + entering the PANZOOM phase, there is a single IN_PANZOOM + state that smoothly turns the just-landed centered image + into a panner. And when exiting PANZOOM for transition-out, + the final RECENTER state does a PANZOOM that lands the image + centered on the screen in preparation for TRANSITION_OUT. + + To do PANZOOM only, set 'transition' to 0. + + To do TRANSITION only, set 'pan' to 0. + + The full cycle (before loading a new image) takes 'image' + seconds (and is inclusive of the 'transition' seconds). + */ + if (zoom < 1) zoom = 1; /* zoom is a positive percentage */ else if (zoom > 100) zoom = 100; - if (zoom == 100) /* with no zooming, there is no panning */ - pan_seconds = 0; + if (transition_seconds < 0) + transition_seconds = 0; - if (pan_seconds < fade_seconds) /* pan is inclusive of fade */ - pan_seconds = fade_seconds; + if (image_seconds < transition_seconds) /* img is inclusive of transition. */ + image_seconds = transition_seconds; - if (pan_seconds == 0) /* no zero-length cycles, please... */ - pan_seconds = 1; + if (image_seconds <= 0) /* no zero-length cycles, please... */ + image_seconds = 1; - if (image_seconds < pan_seconds) /* we only change images at fade-time */ - image_seconds = pan_seconds; + if (pan_seconds < fade_seconds) /* pan is inclusive of fade */ + pan_seconds = fade_seconds; - /* If we're not panning/zooming within the image, then there's no point - in crossfading the image with itself -- only do crossfades when changing - to a new image. */ - if (zoom == 100 && pan_seconds < image_seconds) - pan_seconds = image_seconds; + if (fade_seconds == 0) /* Panning without fading looks terrible */ + pan_seconds = 0; /* No need to use mipmaps if we're not changing the image size much */ if (zoom >= 80) mipmap_p = False; - - if (fps_cutoff < 0) fps_cutoff = 0; - else if (fps_cutoff > 30) fps_cutoff = 30; } +#if 0 /* This if flaky and probably not necessary any more */ static void check_fps (ModeInfo *mi) { -#ifndef HAVE_JWXYZ /* always assume Cocoa and mobile are fast enough */ +# ifndef HAVE_JWXYZ /* always assume Cocoa and mobile are fast enough */ slideshow_state *ss = &sss[MI_SCREEN(mi)]; - double start_time, end_time, wall_elapsed, frame_duration, fps; int i; @@ -1041,6 +1630,7 @@ check_fps (ModeInfo *mi) ss->theoretical_fps = fps; if (ss->checked_fps_p) return; + if (debug_p) return; if (wall_elapsed <= 8) /* too early to be sure */ return; @@ -1059,24 +1649,51 @@ check_fps (ModeInfo *mi) fprintf (stderr, "%s: only %.1f fps! Turning off pan/fade to compensate...\n", blurb(), fps); + zoom = 100; + transition_seconds = 0; fade_seconds = 0; + pan_seconds = 0; sanity_check (mi); + if (verbose_p) + fprintf (stderr, + "%s: tr: %d, pan: %d; fade: %d; img: %d; zoom: %d%%\n", + blurb(), transition_seconds, pan_seconds, fade_seconds, + image_seconds, zoom); + + ss->state = LOADING; + ss->redisplay_needed_p = True; + for (i = 0; i < ss->nsprites; i++) { sprite *sp = ss->sprites[i]; - randomize_sprite (mi, sp); - sp->state = FULL; + if (!sp) continue; + sp->state = DEAD; + if (!sp->img->used_p) abort(); + if (!sp->img->loaded_p) abort(); + if (sp->img->refcount <= 0) abort(); + sp->img->used_p = FALSE; + sp->img->refcount--; + if (verbose_p) + fprintf (stderr, "%s: %d: deref img %d\n", + blurb(), sp->id, sp->img->id); + sp->img = NULL; + destroy_sprite (mi, sp); + i--; } - ss->redisplay_needed_p = True; + for (i = 0; i < ss->nimages; i++) + { + image *img = ss->images[i]; + if (!img) continue; + img->used_p = FALSE; + } - /* Need this in case zoom changed. */ - reshape_slideshow (mi, mi->xgwa.width, mi->xgwa.height); #endif /* HAVE_JWXYZ */ } +#endif /* 0 */ /* Add "-v" to invocation of "xscreensaver-getimage" in -debug mode. @@ -1120,14 +1737,18 @@ init_slideshow (ModeInfo *mi) if (debug_p) verbose_p = True; if (verbose_p) - fprintf (stderr, "%s: pan: %d; fade: %d; img: %d; zoom: %d%%\n", - blurb(), pan_seconds, fade_seconds, image_seconds, zoom); + fprintf (stderr, + "%s: tr: %d, pan: %d; fade: %d; img: %d; zoom: %d%%\n", + blurb(), transition_seconds, pan_seconds, fade_seconds, + image_seconds, zoom); sanity_check(mi); if (verbose_p) - fprintf (stderr, "%s: pan: %d; fade: %d; img: %d; zoom: %d%%\n\n", - blurb(), pan_seconds, fade_seconds, image_seconds, zoom); + fprintf (stderr, + "%s: tr: %d, pan: %d; fade: %d; img: %d; zoom: %d%%\n", + blurb(), transition_seconds, pan_seconds, fade_seconds, + image_seconds, zoom); glDisable (GL_LIGHTING); glDisable (GL_DEPTH_TEST); @@ -1150,98 +1771,38 @@ init_slideshow (ModeInfo *mi) if (debug_p) hack_resources (MI_DISPLAY(mi)); + ss->state = LOADING; + ss->now = double_time(); ss->dawn_of_time = ss->now; ss->prev_frame_time = ss->now; - ss->awaiting_first_image_p = True; - alloc_image (mi); + get_image (mi, TRUE); } -static void slideshow_idle (ModeInfo *mi); - - ENTRYPOINT void draw_slideshow (ModeInfo *mi) { slideshow_state *ss = &sss[MI_SCREEN(mi)]; - int i; if (!ss->glx_context) return; glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *ss->glx_context); - - if (ss->awaiting_first_image_p) - { - image *img = ss->images[0]; - if (!img) abort(); - if (!img->loaded_p) - return; - - ss->awaiting_first_image_p = False; - ss->dawn_of_time = double_time(); - - /* start the very first sprite fading in */ - new_sprite (mi); - } + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ss->now = double_time(); - /* Each sprite has three states: fading in, full, fading out. - The in/out states overlap like this: - - iiiiiiFFFFFFFFFFFFoooooo . . . . . . . . . . . . . . . . . - . . . . . . . . . iiiiiiFFFFFFFFFFFFoooooo . . . . . . . . - . . . . . . . . . . . . . . . . . . iiiiiiFFFFFFFFFFFFooooo - - So as soon as a sprite goes into the "out" state, we create - a new sprite (in the "in" state.) - */ - - if (ss->nsprites > 2) abort(); - - /* If a sprite is just entering the fade-out state, - then add a new sprite in the fade-in state. - */ - for (i = 0; i < ss->nsprites; i++) - { - sprite *sp = ss->sprites[i]; - if (sp->state != sp->prev_state && - sp->state == (fade_seconds == 0 ? DEAD : OUT)) - new_sprite (mi); - } - + slideshow_idle (mi); tick_sprites (mi); - /* Now garbage collect the dead sprites. - */ - for (i = 0; i < ss->nsprites; i++) - { - sprite *sp = ss->sprites[i]; - if (sp->state == DEAD) - { - destroy_sprite (mi, sp); - i--; - } - } - - /* We can only ever end up with no sprites at all if the machine is - being really slow and we hopped states directly from FULL to DEAD - without passing OUT... */ - if (ss->nsprites == 0) - new_sprite (mi); - if (!ss->redisplay_needed_p) /* Nothing to do! Don't bother drawing a texture or even swapping the frame buffers. Note that this means that the FPS display will be wrong: "Load" will be frozen on whatever it last was, when in reality it will be close to 0. */ - { - slideshow_idle (mi); - return; - } + return; if (verbose_p && ss->now - ss->prev_frame_time > 1) fprintf (stderr, "%s: static screen for %.1f secs\n", @@ -1256,9 +1817,7 @@ draw_slideshow (ModeInfo *mi) ss->prev_frame_time = ss->now; ss->redisplay_needed_p = False; - slideshow_idle (mi); - - check_fps (mi); + /* check_fps (mi); */ } @@ -1274,44 +1833,27 @@ free_slideshow (ModeInfo *mi) ss->font_data = 0; # if 0 - /* The lifetime of these objects is incomprehensible. - Doing this causes free pointers to be run from the XtInput. - */ - for (i = ss->nimages-1; i >= 0; i--) { - if (ss->images[i] && ss->images[i]->refcount == 0) - destroy_image (mi, ss->images[i]); - } - - for (i = countof(ss->sprites)-1; i >= 0; i--) { - if (ss->sprites[i]) - destroy_sprite (mi, ss->sprites[i]); - } -# endif -} - - -static void -slideshow_idle (ModeInfo *mi) -{ - slideshow_state *ss = &sss[MI_SCREEN(mi)]; - double allowed_time = ((double) mi->pause) / 2000000; /* 0.01 sec */ - int i; + /* Doing this causes free pointers to be run from the XtInput. + I don't know how to shut that down properly. */ + for (i = countof(ss->sprites)-1; i >= 0; i--) + { + sprite *sp = ss->sprites[i]; + if (!sp) continue; + sp->state = DEAD; + destroy_sprite (mi, sp); + } - for (i = 0; i < ss->nimages; i++) + for (i = ss->nimages-1; i >= 0; i--) { image *img = ss->images[i]; - if (img->loader) - { - if (texture_loader_failed (img->loader)) - abort(); - step_texture_loader (img->loader, allowed_time, - image_loaded_cb, img); - img->steps++; - break; /* only do the first one! */ - } + if (!img) continue; + if (img->refcount == 0) + destroy_image (mi, img); } +# endif } + XSCREENSAVER_MODULE_2 ("GLSlideshow", glslideshow, slideshow) #endif /* USE_GL */ diff --git a/hacks/glx/glslideshow.man b/hacks/glx/glslideshow.man index d1ab1abc2..c22698272 100644 --- a/hacks/glx/glslideshow.man +++ b/hacks/glx/glslideshow.man @@ -9,22 +9,20 @@ glslideshow \- slideshow of images using smooth zooming and fades [\-\-root] [\-\-window\-id \fInumber\fP] [\-\-duration \fIseconds\fP] -[\-\-zoom \fIpercent\fP] +[\-\-transition \fIseconds\fP] [\-\-pan \fIseconds\fP] [\-\-fade \fIseconds\fP] -[\-\-titles] [\-\-letterbox | \-\-clip] +[\-\-zoom \fIpercent\fP] +[\-\-titles] [\-\-delay \fIusecs\fP] [\-\-fps] +[\-\-verbose] [\-\-debug] [\-\-wireframe] -[\-\-cutoff \fIint\fP] .SH DESCRIPTION -Loads a random sequence of images and smoothly scans and zooms around -in each, fading from pan to pan. - -This program requires a good video card capable of supporting large -textures. +Displays a slideshow of images, with panning, zooming and crossfading +effects. To specify the directory that images are loaded from, run .BR xscreensaver\-settings (1) @@ -48,58 +46,50 @@ Draw on the specified window. How long each image will be displayed before loading a new one. Default 30 seconds. .TP 8 +.B \-\-transition \fIseconds\fP +When a new image is loaded, it transitions onto the screen by sliding +in from the edges, spinning or flipping. This is how long that transition +takes. Set it to 0 to disable the transition effects. Default 3 seconds. +.TP 8 .B \-\-pan \fIseconds\fP -How long each pan-and-zoom should last. Default 6 seconds. - -With the default settings of \fI\-\-pan 6 \-\-duration 30\fP, each image -will be displayed five times (30/6), and then a new image will be loaded. -If you want a new image to be loaded at each fade, then set \fI\-\-pan\fP -and \fI\-\-duration\fP to the same value. +Once an image has been loaded, it is panned, zoomed and cross-faded against +itself. This is how fast those pans are. Set this to 0 to disable the +panning-and-crossfading effect. Default 6 seconds. .TP 8 .B \-\-fade \fIseconds\fP -How long each cross-fade between images should last. Default 2 seconds. -If set to 0, then no cross-fading will be done (all transitions -will be jump-cuts.) - -Note that fades are included in the pan time, so \fI\-\-fade\fP cannot -be larger than \fI\-\-pan\fP. -.TP 8 -.B \-\-zoom \fInumber\fP -Amount to zoom and pan as a percentage. Default: 75, meaning that -75% or more of each image will always be visible. If set to 100%, -then the images will always fill the screen, and no panning or -zooming will occur. (Images will still smoothly fade from one -to another if \fI\-\-fade\fP is non-zero.) -.TP 8 -.B \-\-titles -Whether to print the file name of the current image in the upper left corner. +When zooming and cross-fading, this is how long the "fade" portion takes. +This value must be less than the "pan" option (it is inclusive). +Set this to 0 to disable the panning-and-crossfading effect. +Default 2 seconds. .TP 8 .B \-\-letterbox -In "letterbox" mode, when an image is not the same aspect ratio as the screen, -black bars will appear at the top/bottom or left/right so that the whole -image can be displayed. This is the default. +Whether to fit the image on the screen (adding horizontal or vertical +black bars) or to fill the screen (cropping the image). This is +the default. .TP 8 .B \-\-clip -In "clip" mode, when an image is not the same aspect ratio as the screen, -we will zoom in further until the image takes up the whole screen. -This is the opposite of \fI\-\-letterbox\fP. +The opposite of \fB\-\-letterbox\fP. +.TP 8 +.B \-\-zoom \fInumber\fP +Zoom in on the image a little bit. This applies both to "transitions" and to +"panning-and-crossfading". Default: 75, meaning that 75% or more of each image +will always be visible. If you always want to see 100% of every image, then +use "letterbox" and set "zoom" to 100%. +.TP 8 +.B \-\-titles +Whether to show the file name of the current image in the upper left corner. .TP 8 .B \-\-delay \fInumber\fP -Per-frame delay, in microseconds. Default: 20000 (0.02 seconds.). +Per-frame delay, in microseconds. Default: 20000 (0.02 seconds). .TP 8 .B \-\-fps Display the current frame rate, CPU load, and polygon count. .TP 8 -.B \-\-cutoff \fInumber\fP -If the frame rate we are achieving is lower than this, then panning, -fading, and zooming will be disabled. Default 5 FPS. - -The idea here is that if your machine can't maintain a decent frame -rate, then it must not have fast 3D hardware, so we might as well -behave in a simpler manner. Set this to 0 to disable this check. +.B \-\-verbose +Prints debugging info to stderr. .TP 8 .B \-\-debug -Prints debugging info to stderr. +Draw some diagnostic rectangles. .TP 8 .B \-\-wireframe Another debug mode. @@ -123,16 +113,12 @@ The window ID to use with \fI\-\-root\fP. .BR carousel (MANSUFFIX) .BR photopile (MANSUFFIX) .SH COPYRIGHT -Copyright \(co 2003-2005 by Jamie Zawinski, based on an earlier version -that was -Copyright \(co 2002 by Mike Oliphant. - -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-2025 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 and Mike Oliphant. +Jamie Zawinski. From b1a082f0052a874799ced4561a74827a3bb2f9dc Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:25:50 +0200 Subject: [PATCH 17/25] hacks/glx/texfont: Fix on iOS iOS lacks support for some OpenGL APIs, skip them --- hacks/glx/texfont.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hacks/glx/texfont.c b/hacks/glx/texfont.c index 8a957f191..43a4d64aa 100644 --- a/hacks/glx/texfont.c +++ b/hacks/glx/texfont.c @@ -147,8 +147,10 @@ bitmap_to_texture (const texture_font_data *tfdata, Pixmap p, XImage *image = 0; unsigned char *data = (unsigned char *) calloc (w2 * 2, (h2 + 1)); unsigned char *out = data; +# ifndef HAVE_IPHONE GLint rowpack = 0; GLint alignment = 0; +# endif /* HAVE_IPHONE */ /* OpenGLES doesn't support GL_INTENSITY, so instead of using a texture with 1 byte per pixel, the intensity value, we have @@ -260,11 +262,14 @@ bitmap_to_texture (const texture_font_data *tfdata, Pixmap p, image = 0; +# ifndef HAVE_IPHONE + /* iOS gives us "invalid enum" when trying to read or write these. */ glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowpack); glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment); glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); glPixelStorei (GL_UNPACK_ALIGNMENT, 1); +# endif /* HAVE_IPHONE */ { # ifdef GL_INTENSITY @@ -295,8 +300,10 @@ bitmap_to_texture (const texture_font_data *tfdata, Pixmap p, } } +# ifndef HAVE_IPHONE glPixelStorei (GL_UNPACK_ROW_LENGTH, rowpack); glPixelStorei (GL_UNPACK_ALIGNMENT, alignment); +# endif /* HAVE_IPHONE */ { char msg[100]; From c72242a7c425824873f894f3f1e12753457cd54d Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:27:41 +0200 Subject: [PATCH 18/25] hacks/ffmpeg-out: ffmpeg>=8.0 naming of H264 macro --- hacks/ffmpeg-out.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hacks/ffmpeg-out.c b/hacks/ffmpeg-out.c index c3e94153a..e894e9b07 100644 --- a/hacks/ffmpeg-out.c +++ b/hacks/ffmpeg-out.c @@ -51,6 +51,12 @@ # define HAVE_AVCODEC_GET_SUPPORTED_CONFIG #endif +#ifndef AV_PROFILE_H264_BASELINE /* ffmpeg < 8.0 */ +# define AV_PROFILE_H264_BASELINE FF_PROFILE_H264_BASELINE +# define AV_PROFILE_H264_MAIN FF_PROFILE_H264_MAIN +# define AV_PROFILE_H264_HIGH FF_PROFILE_H264_HIGH +#endif + struct av_stream { const AVCodec *codec; AVStream *st; @@ -403,7 +409,7 @@ ffmpeg_out_init (const char *outfile, const char *audiofile, ffst->video_ost.ctx->time_base = ffst->video_ost.st->time_base; ffst->video_ost.ctx->gop_size = 250; ffst->video_ost.ctx->pix_fmt = pix_fmt; - ffst->video_ost.ctx->profile = FF_PROFILE_H264_HIGH; + ffst->video_ost.ctx->profile = AV_PROFILE_H264_HIGH; av_log_set_level (AV_LOG_ERROR); /* Before open_stream */ From 7daadaafe1dd65a1e050bf6123e5630c0a0a0eb4 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:28:16 +0200 Subject: [PATCH 19/25] hacks/fonts: add/remove fonts --- hacks/fonts/Makefile.in | 5 +- hacks/fonts/OCRAStd.otf | Bin 30636 -> 0 bytes hacks/fonts/gallant12x22-bsd.c | 6198 ++++++++++++++++++++++++++++++++ 3 files changed, 6200 insertions(+), 3 deletions(-) delete mode 100644 hacks/fonts/OCRAStd.otf create mode 100644 hacks/fonts/gallant12x22-bsd.c diff --git a/hacks/fonts/Makefile.in b/hacks/fonts/Makefile.in index 4afc13e32..2ba4b90f7 100644 --- a/hacks/fonts/Makefile.in +++ b/hacks/fonts/Makefile.in @@ -15,10 +15,9 @@ FONT_DIR = @FONT_DIR@ RM = rm -f -STAR = * TARFILES = Makefile.in \ - $(STAR).ttf \ - $(STAR).otf + $(FONTS) \ + gallant12x22-bsd.c INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ diff --git a/hacks/fonts/OCRAStd.otf b/hacks/fonts/OCRAStd.otf deleted file mode 100644 index aee7c35769d627a169204c1753c7178cdd149086..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30636 zcmb@u2YeG(_CGqZJTvwPlm#OK8fL~2z=UE`6G9RaAOR9;FumH~URB&xExF-t*;a9t zEz7;oYakFvBaJjRZ4)-hhGG&Y+1=dnj#>U^gtPm5@BiNWeBS#!3u(&j_nv#o_ngb7 zty?!?V=*%(#Wt^85&mLHaLrK++j9@Yuw|=OuMVEH^Nk7&qu_bn#TUX~TBD?cr(xLM zSr|s=t=YUOyd$R_()KtZ|CTl3+g4uK_FgrH?R*cz{H|>Z4_mm?oAxD!NuG!Fh(pPd zs`I}@t;R570*3jYiHnYm`se;zry=cY_&yN_FNn4W(;+{kW7Ff3)3R2Fzo5pj?Y&SR zn;e;?lE^nhl4L3T5Gj$#(c=~u7sIm~>eHxFwP_DN!lI$S&^{K7N#NJ-k#Em^bjI(% zBhUO3lS*&H8|f$e-}U?R@6X5GzM6bV zqd$;iGbWM4lfU0}NhOA30e;1PVy){QUM2gnD9I|Zc_I*#_!CkR(xjuMeU}w4tb9>& z2@4kd9<~L27z*~a4W(!)1(|{|fB02M{QlGav+yjAO8gDPo*ljS!$@rP=)Dx1gl!nT z_x~SxaBLaO%)_z-I9s31(Eb$M7)^cD)9^Ol^@sje< zdp}GLGym|t6q_&UAHDa7_uq`(<5-&H-snB?Ki&smi~S---v?p`{c1+6UrITY3ahS(OpA^R4PKFy6s(Dl zjZ4!8YofK$nhbckY1NkC6~WYs+B6_5ZAn^wNKJzArU zPfZDan7%n&yqQ1$>A2LiL#Zhl!3#p?hd%M-)5(#E(Wz-Mp-J%v7ltkgU9@Py6H7;{ zS&h@*WPdYKA65J!{({S#+I%pD4?KMASH(4R!8Ps|eo zZbD)X;9-bEDS!GzE3EW{$q7RedA7sw6xKd|KFDggEw#Bp1nS(3y#jO`j%~%ZVcW4C*iLL0wj0}n?Zx(C`>_KsuuiNS>&5!8 zlh_&TB6bCP6T6DNfxV5rg}sAa!`{c<#oog{z&^r0#I9o>W1nC*uurkifSY~+vh7Rk zD_Hd=nCF8)0~$Z9_8s;Ob{Qz-ChUMD z2`LExnpFAdFbnIz`hnvQU`Mc{*fH!lb^<$vi8A;s_9}J(dkw3=^q2uNVkXRtSuiV> zhvj1hAm`d3PZZ1~4yz!p!2#%z5p!c6?15x~WThlr5-G`&7$r8pxBTAm`-}8a@SlPw z1S^Bt;Az1#gXae?3w|NEcWThoX;WuT4V~sUjhObxwDHpv)0ETLX>+Enofa`Idiu&4 z*KSI0l7ioZ2hduuZ>1w(-rO)>ZP3aJ$recjv|@l(-h@^@_q7rfJSlieaImkHr~WTm z83(OQ{!c4W)1QY{u$#CbdGO%DU$GVNRl+yo!D|@yU_Z1Ae-B>5uz!C7-={F_{`{LG z58q42lzjs_$ybwL z0DmWl|Ll`Ls@M)&hLVhtfcEe|zwk6cGEt(GuzzIyKVK!F6NukG{y;AP@jUtz3v1H| z)RhZ#br|TQMk0YZGXmAQBr+(a1G-WJ4Ok_CKvNl5J?4a2%?1i;2a4$N(RUG0_z|G- zexQyMqtxL5ia+b4kaIx!Z9u87`RL>#b_uHkI(`%O!d2J@Z@^9{hrRGV>;`c!d<45e z+zTGq4L4vvdlk+V-krZ zU{q#{_w)D{F#bgezuJ#qE#)8eFC8Np8smRIO0Z7B-NWzVQ^u}%WXjn0#+{z>{D$$^ zTu~GA2mU1kj->!T6$~6`G4Pi)z(uwLor)4E3;JIKyT}gXYloRV2J?3XX5~}h0=KYV zvHP$d<0Zk8xspYaXC-SSuSm8_>LqP42jXK6B)yofNqr$YDJ^nSGDv$>d{VSl8?8={ zOp4V+gPNo9-KV6c`L2;Fl_oXIcN?D)6Q2^FmYtNE6P*$p9iNgG9jl2E%riMoF@9e1=BK9|5J(BnfVLmNB-xP*}i)Je^DZ_YH|H%ft)#loyUH|1j(b4g_0K}YhexdNLnSGl3vMq$z{pU z65h|xZ?@kuzvX@gzh=MVepmh8m#&hok*=2}NDb0Fsax71?UUY<{!@D2f2IE#{}}&F zf4zUJe~15Z|119g@_&F&$CL3K+=>_DmH0bE01-q?Cc=p*!a@`ft;7-H0`WTWHF1~t z2f-5~q=cMEP9YbN%gE*AK{AhQC*LC9BR?WPBflhXlE0AuAbIkBfFvL=KoKw{U`{|- zz|w$c16Brv2kZzq6c8Jb8ju}e4JZp}4CoCwA8;+;lYlP+z74n&@Xvq;fnx$E2Qq=v z0z(6z3|tZTV&F@GTLTXSCIqGjnga_1O9SnJ?!dOd{=id#=K`+;z7_a>;KzYC_{aH8 zitF{JRb2WeDslmZzI=)i_A4&c>9%tj2dH<+{-ZW8D=Qg9GY0<|O9eAB-aGLLN;pU) zW>vV1oYsry+43AU${zGKd9|kgb?$TWQvQ(x{cKb>-W8KxxtCrR(< zt$ao3CZQjHA4DOWscF!UThB9zM4G0`W#z1{VsCLvE;>Ky5K}9>Ubdt7;Hj9&s-7-u zJNTYk(bY$0YU9suq+i77bv1-%4=QeaFUD9$WV>;fF+o4ZWhVLtnXN8GG za&k7~&2BVssRMn7FVJWfaqIoF_pT=%+t9%Yc}RjAs!Ub&%I?0xW>!W%M#%=WF10L? z;vT428M}r7}gE z$8lspYu9iV^ph~<5OrKA%Oy0`OdBUlrDldQf0l(XxicA=JA>a8OQ8q+YDHCTZFw!- zL%dO$wmFh&OG&GZpVfG-Aw&{|LS)1` zk*3;ZQvUM9SVnk~*q>W|B9nUpt-wtlOM{L14z0wGHrXmp(dcOcax5p7N2pfEb78`U zGAgklp1mb(#9!_?m3)JiNp>~s5^8YS=7_=r z`?!e6qC;DiM%7_PmKdLRP^L(($W&{U`^c9mZ==Ui#iDz$cvoSw*P}d3E@#x)T2nqN zMJM^q#czA@BAcz)Mt3&1w>MboGi$g-$M9-hc4ZcwompVWi^YThzCuOQsIW@Xw3-^5#o>$+P-$XYyRXN?9%u4ZNfH=qSH7`)|)OZHXeU?fU z$@j)uN`~+u9U~)ABg)3xJr(5x%Gb%>l1g<8`_xCc!(gq3w#*i@i4z)y3|v>n)VpeH z9W1Is$*)Gj)t6}fdeED~QC98R;F z?rdoG)aTpHPEN*$qP;IO!t6zqY!D4?rl7tsvd!X&jxlL9tWbgGgpokN~ z*=%#xwJ2K+t}Gkuc@p+)bc|W6W`zJ!{yloMxy#;CdTes>F>_01myFmMl^=JI(`F_d zOi-#@vb;UDUXPRQZR{@XrDY`vz=PtO%wG0&!rNr;r8ZaiyFrib61Of%qD)vgB4+XiY|j)>LJ5=5pwf*^siQrzidz zeXXbOd=DpUZFdbEO?9MmGDQ+4BY~g7KnGnccY=IXUYX{pMQN6FaA?K@;0ba%biW8-8Ij6^m(;hqGoMI%y_F`TYQ(wk!A>I~f+ zY9YE^uKodoBZ-rHyW8uVxi`+@S58-YuPf&m71;%5y^&qD3Ab9z79%Yq2dY49{!X4L z>`v)qHSKtt)>x59uOPIhVr?pyog>T4t9RvbbI=yt+>+nuRrXdl)pfFeLoea=)s-$c zEfXSO;qE7G1Tq>oC|gURcv-B+|Ni3L4_aWkQxdMm8R3 zRz^7O7HbXn$tJwcSZU5y%1IE1QiNYnX!F|DDL~Te8JH}zJ97milOPVg`~`YhDob>L zoOFnC(vX&;Ri?VNoiY%AKeq0D^0~;wRh+PvkSRWm9$3K&1hFDIb|uKb)O3&uLJg^I z(RKjeU3oP2GZ1&gXGaG<Mb@u4zui&4Ls6*PoAp9ztXMj)0`&Nh$7=!xJ!N8wKnO3())Yd>gGYqbvb2~L(+ z5r6u0MPCnlPe!(x+M=UP8Vw5*(jv~rAipV7_Tlg<2^!05U~-a;F|i#6pjsO&M~|gD z>Of%(NbQOIjn_tQkaB+RkT3TS{Bfx)Gaq!Juh0$&bTtGBI!GatV3I^EbtdK*gL$P` z_cF<0Oya^MHcT>rNlGwD4JIkZB(<2tfl2I`qzaQ%V*rjzDlkczL{f@L3MCRRCh5T> z-I$~SlXx&myPu>Flhk7pHzsMqBrTYv4U=?X5`d>0F-aW;n6ji5!;&RnPJyio2B@SL zlQ_Y07FBT(w5b49d_?lHq|k4H-!p#Ies`tYrD|!hv{YIny)6CIp8)mR?tc-ViO1uo ziCM&cB9*WaUl2c%bIAzuJo$UTY*2@v3D_Kv9Pn|#cL99hQ-MZMYd;Dcp;l1|GC$cC zS)r^;_T!jYW6Wc2jp4^m9Q)kZ#Ig3Ve;xbl*paah8MeKI#WX0m#+ZgT!)*W`1`F-pDiu+pyV zRlcgcNC(l6(M#xUbRvC)zD+-v^2n6vDX~)qm^h|{DPyOw92>)a%M}7RGC$ZH{L@s~ z)Fo5*PA#80F!htEccx9B_R_TEX&+Ae{;|{3L#BJD_f9`P{p0Ch%vd;M#f&{O4$VlK zQ9Q#oqi#m)jPo&D|-AOCdr-r1%(0^PZn)oA*QLnovt&;?A5S~VVA2H19cC56a-mvSj;e7monC_{RE@-^5%Ed9Ly!(ny!a&M zgeSSY1O*R|&#a@+cgLuRLiL_{0*G&EU9WuYX^;JwQz3(C5+ifp)n|gY;SFC=g_lc zds?fC74BU}_hx}Ij>ZtP85s9^kmBomDYW}1v|Gym$RkC4V`+a*V|G(iu_1e8>PX!r zU3PI?LpHFxvbu%l&0?Zbt-RWvncBFa0Q>QWHuvxlb zg#UgE?`*3oJF5JM{BG05Cs{#CEZwqoDfc3oUSb8!;?B%vFW{-#lEOIUdh%dxY)>+) z>g>%wO8-c7mzOuSa@Q_h+>RR^4of55+0@d}n$oGS*A&%4p;Y;l$}(fx#Y=`GH)M?Ffe z0*B`sjQSi9V(IN3dtHNz{Ta#e)0bWSABk;UHw+xO%*y}D|7M`jJk+VkDP!D?jm|pu z_E)$teG!GGleeG7jdhLLpp&^h9iFs?92X}%iu}=Z^a$>>yTrxFXiL!z*o)9pZ9v8`^nUeG| zQhsheRpQdsu`a#2B%2mCx~OmlP0&$j!VD^d;%^VHRaDt49ra3Ynp>?gWoMe$5$e7I z&()c7vXtt!jJ7t1%k5z0I~Wvyj7q2OFH`V0&^b{&nW62Wdq7H|LyF;LLP;TmLPl-~ zA&)aWOL#r50S;A?okn*|j4>mH750;I2Lnop6vd-k3e->ZwpO;baUI_B_5me|BnOJx zQ@w1fCap4o7H&SypnHN<=p&wwj((mKzKo-Ud&D0ieMrJrK)V&g%M`*gGCVyel@)eE ziJe48OHMc^EEDcQXYLVKPo28Tp{?X`YiCji+uc#!d0YvPS0hesfo9meFC@ls}EEL+7ENIzpG` zsxolNPQ21=DL2t-P-5b`EbS)lXbx^}tIPA!NJ9*GE4tb^cUyT&w-P0g{Y4&e$Xab> zA}y@<4KH*EeV)lc^_}kKE^mfM&21v$tg1Bb{ycJDW6n92$A~k{_2)R0MxM=e?_!1T z2y`w)A%qI&P$(%crG6f|`^Vg{&g{ zJjE6LN_1*uGnts3n$GPa(;HKJdKx=g*#8VXpD7u-GgLAZbPpKdIt8-c5v-&z9o8{k zCn{?v$)MkowC0>_P-88cB&A>>Hy(|8hehXzca9!=n?n||+tQZZzy|%JAzN!tqR~mx ztMh;rUIYY%tYpw#bWX7PX5hvUnqSWhDN-^rlU2=WUEBqts~Py=@G{by?nz}w*h+D2 zg>yp+G#^UMC*>#ztw-~Ls)MFdpP<__U|~@hT0b7eqTSHx+x)zIs??QZp@hwkGeN)H zMAb8>eg@_9^A(6kX1vK+@A4`;iqpI)wBC?sHE|>Jh4yrV&QzK@Ii=3rVqp0&!HZiR zE=vR5;c4&SirY-iOlN?+l0sE+K=3Foj*&y1a2c?w%N+C1}I$V=c zP!z9Rv50zm7b6spG$>SQT9v9by}hHQrM)A)HI45AZ*Xg`Rlv4eNvBSmA;Q;H?8 zJ#)LSzuwcvs@skl`sstz;seZ3GPA$vOfQRa$*VfYR(1_BXUEEg910g^DD<`s+xHc{ z3W-z5tF2BidzN@8z5qs&Ab;Lc#2iIqa1>7*5yot%gl)r5;odw`TLPVE)~c)=QjF|V z2n&cWkOwa#{@CyMMAS>5pzl6MkA7ykwB<5)>74V@8%i{F?canDR_G;$M%F3H8UBWU zIV108)`E}&V>z56h9;^gu@)(SK~~^w);-kyCJ_vRPVvtSq0n|P4KFC>Fg%5dpM|+W zp?jbJDE{I$s%MZ*F@rpiY>j1wMZ^|U!|NQ{NxoWgvilf|z(&DO_7)buPNOlfk(I>D zaXC8=aRMdG!J~H@64oh&a&ng~=6Ecd*xzRb)b4rW?t5?D;{fZ}RmjMrDcEo)=Kw>5 z4dvqz{0#%chYl|T_zbw94?dHds8R01Umi|U%w|SDCikfGBf;$5Y^r~QLlc3)&ma#~ zrM4xodj`(uUZLM0-nr0lwU2A+EAbpv%A*)yH@-0<9f{5e6}YLsK@=cOo{mP7%V_6> zL39rNgwEj(yC~s0vOFL_a&rL{ctddDC}$2O@1bA@hXbIqNpa%b4NpL9$pCW?xc7u9 zL9e0_{%3_CM=#*QxO67yYyP`3@~$uy*O5uCl!2p;&Th7zyo;vdWh38hq=u7(airKU zbYA2$=sCqGo6*>zrdDz7u^7&|*zQI}Gk1;{~uwmF@hBW%G9d3m}_TFbaA4LU$3-5ELt z9mxa{qClyHi$POrDB)&0GaTR#ob^qoehViAH!;xK@`;Ef`n#)7_GlZExy^*;tv4^? zZ(eLZ{kak~lArCq@?30Mb{fDK5yDD*+dlQal}e$GJXERbNMbdu-NrupSgYOB!M%S4 z??gKlUB>*rC|a$}Q0c3)fyaAaTJk)eXEj^RbXsXsJ%=3R8GBP-CyVw0pk}MF)jH^w z!&)6Dl#!eA4Ev(lv@Bet*k!=kG8ulEqLo0MBP_17J59}WM{83@lcC96#|i1^27Zh9 z>WlMtxa;H(&s=$i6@GX)KrPXAqTmp>nmlyiFbF%aNI@WH4Ubb4R+#~nZ)h#D0}D!^ z9GPwviv~wF;1&5Uy;Z5#lv`OLSxxC%Grb&02j7}6Mb|*W+z(g;L~$<`=y%G9MVPXP z8X$pGL=nxuGV#JO$FY8{_ekZyStb8EVA!vd;W>u=ETDw@b6i)r(RceQV|!!RsQzQ7 z3$#dCO#nBe5wsCh5`H|676W}RB#otpN)wC1M}U{r)?{_l-8D^ZwZL+C9bV}ubvc!2 zA!J-EO4{LN1r(n@vA?FOtAXo(8+W#pmbEJnQ+x0TLUkTTAClcZbUTR^J|tD6Zx2(Y zhn?wc|3*Byp(ekdzCrXg+Xif084+u1&g-M)85A1#jUvwskh)Us$!P1fw|QKm{IjB9 z!HR2Lc1)RN2)?+@UTJqJy;`>>!K~35SOIbiPzv`L%)s?D+6=X! z(rg2TY_;&FxX8mz(EU)J0F>?1MU;<`iKa#xh2AEFe~k$EdeCIvA&|fia0t(G)H{@=0_J_ZTfLiF8tKx)y-RCxvUcRc`@J zSlgV{>aBG(Ia#@|Xh>2r93|cCA2J*@MEdl1e#h{hos@hkBQIuI0$K%=F zRNUkmNbjL<6P>;8jxNsa#`DR<+Qg$LY<;~f{|opyK(*C1;Qeu`M$lZJ7Gf3cC4F@c zwzCzlbvSAq^oN9_p^I{vvX#PEGTUGR#CGdmT$i0=HPLGblc@%}mC}mq9VLD3O8H}q z$SXDt{tCjp2?Tl5`-)W*KlVQ^h8sk0ukFN{nDPYfuJZ2 z_t_f1Q}Xd-PeFfVf=->xnn`UF-WikBq^3g&jUMoHPJ5;CQEr$9(Sk*H`f%q zo0SiT3aBACN!ss9`Io?>bGayXUnJFkD83|%UPmORj5<3|B24wjuRbRSn)ULF&is(5}a`G5=>_o|lOG>fo;r)>eEYCnD zN`XF0ks5snI^-Wclat2>P`9S^g&B}JU8+<%-MV7$z!;! z+E!zy+YTp#Z2HXiQvM<%pGL`#QfU1kFCEOHULsTwnyKNka&QOP!;Jg}*|w2Q*?3BK zbLuJjJwnZB2$SCFGH@%e}B{{Fy*~@ zeFvi~iHU4JneN6rlareh>7_(HWg6XQj?sOl?ryf8pl=eVyzO2u*U*3qQ9GzPXh@Nv zw>;c3`fQ6OgMNj`*4tb;TzaF<l8kxof(pI!pRP(rTc@-Gd5A zq(oBO)!?jYq&tY#){-0tS8FIS>6A&X)czAyeZ8m6y@@@nSDoaDp_dcMsafeN?)eS) zF|sGOC)(#=lRv}A!S|?vJ^3+^DOv)qrzJlTE2zhl;+by2MeI0y@W??nrthTrJpC$h z@vQA+KUd$>0Gql!-L2AQ>(cVssNC$LD0(;XQd#$9PCnBoA=UwAjz)$Q0*5}qUnTqU zk3_^9RY~j`QdeQM=~?uc@ByA#({RW`ze9K$jyKnE=rQyGZmX-Pu2+IUG`7b_U|xIz8}#ZTa>v5tA97JC-dmhMaFCA7k4+GX ztN9$D9x1hziGB1DqQTYZtl?h!;A=g_oT)QtC*<_|>D2cc*& zmn)PeFWm8iPsbSmJ7JvYshf3I0j?=ywo>IzYwv98bT_bI9L+{@VK$!8(3H{%yQ8(e z(d0A(1`>i+BKYEVm&4fzyThYO$x6=1VFkzyis@|Jos-p-LaQ>gs%(eRZs1S|sBZF= zl>8M&UJE-2Y{Av!$=reDUbeftX5f?(tpU&96e32Im#pD3G{sq9lrAK97<0C>%N}RG zCN4R1c5v_}sWi*2VUye1^N!GH3Ro76j9^v#>qyAIkC0F^Xzz;0K|dmnwA*}^dubC` z?hDD+oDG-QuV+z!Ss5E%~$BsMuAHx_WD)nKO9 z{`BEbk{^Z;80hF5-l%BK6m8+9#IA(co!nwF(Umh$${ukx_Hgfz)fE-h>=B~A+G=!i zh!hAsv)N+j4?Zr+dx_i3$1Jnp|e&yjiRbNJRSwtQT&97 zrz*VXi@0nN2))^V*xGrJK4?veJIrN^VCnTehs)Hb02)0uJYHd^)P$3fqw*oN5THs} z$9Y3np`-KAC4~>A{QV(5`8ya|4QL^1m_-HqAW30NFzJIcMZ+s^2w8F{^!1S9I?BU$ zQ7;O4_@>pA{2&8}6nY2Lop}JWG?Qo>`p)6bIj*mq9PiMY^lDgW$0T7ka_GHUN4#mW zz98q2BLi&{zMGUOgoxOZ5CH&J#6|`r-VnbT+8L5uEM8~{VM^6GM+a}`Ej6vd@o3FowLs3qCIWxZbyL=+@dqkc)UrMRhvO) zXXoj&xjE0`>Di{VG^Ng_vm4lfeT!ejQ_>7twKBa{>sGUUl!h4FY+eN(QRZfvyGHFASr;4O`g)>dVGUcK4H#+>>7W4yD~Gt^$%#{4-&L#2+f4)>f%+3hQoD*PWJK#c#XZn0kIQ+ z)fsg8IwQMdJzi?bEzP9`Igy)NTx{WXT!T*OstmL`Ekm7KVX856m)GKj#>1el0hE|i zrmrxv+t%V1bD=3$scy~iy6USym3r+OUR+aKTuUQ4QCnMD3VVM&OjLb72%lEBx3 zv2)u#z$=^pDJ#L!2H0k%uu+&vfT|}!wIUR~=NKjI{vVLKow0!H1AQiHfyjw^Ko|UA z_yx&F{JTI^eAsTL6*+e^@=k`oHq0oRolaMqvP0`l)#{K6=}nfF&5 zKB@u3M#uyZ#%ZnhfiS%qr?#FG?xGA_tfYnyQwVp#Yp&I4j0s8+eyMj>1N?#pQ6_%0 zt)lFV@)~(8zar5Mm4pAi+N7`6(WzQ>s>W$(hJAy69Fm|}{4-J%<)F}2J%n@AH8A|Y z6w3>#&p~T1WzajHlew@-`Ug=kq{w|KD-mN$*0l;=Wa@lCZP3_chHnOzJF3gqX~)^7?d}0^yd$M!}wEZcOBY& z8SMr*Epu3^u+>yJ9LmlNw@R-o(3!!o80o_EEQJuIl;Y0psB=}-RUv@-6?9ve z%Ktc(;`>Ix2~kR+oiHEqXomtdAsyc4t}O3Uel~~NNJ7v+{)JT!|B$A;&JQv6@~C=@TGp(Wvi+&-E7RywX!AyKy`V= z@$}O~d|qi=24`~NwN_)5nNC+_rPD)Hu8pgdYPmGp1G{ zj9o%%DG>pN5hn7Ol%Fv?Ly>1aY_-BJ*Lv;MmDSbk&@Xs(b$Ly#vNNGgZ8qiS<*`Du z;IAmK7UkzDHLcoqM@r)da{nQ zfV1>8x_W!EU5VThG?tL_Kf#QS46ll2TxM56W239mHD-DuBW|p|;b7?<2gP^7wgN#h zW~fQ@+K>C+G|x0Z{Ti!U(}SL{d(6qL~wn_orLb712kmlaE*%+p1dwg828)TKpTp zA7Wb#UKY)o1+KRcq*Cl9P9YgyLCBw`0B(B>X0H%^p+JXz!QJ-Sh6bfKvn|DHJzQvE zg{4p9=nNnYcgU~zt zrYQDI*v`e^7BOdoTckDJ+vcnTw}|%)zT161@e=*!(cV`*9603g`d-J8qsr6fZUD6o z{O#@E@G5&1Y!q)=ize2PpwhF(H2i$VzW(j>rkJ>0Y7VUf@csqi^@18)-)n9ePMssxrx%Zcwpd!a7`^mv6|V)AQ;ZteoaG zTtr+$fL1O~6#Xw^xEcp>AHIp*MQErYe=Q?_hAO%D+u+v0e-4g+ZwO7jizW{ReS_{E zRd_YH(Pb+Et8pFCNePq7VQ**{{79@AmA5IBIY;;cNP{k>&m^A--?NGfBcFbE|0nDK z(QPZYL*!pLzd})4SqR>~pl|B*WtLp!JYjML6?9Qp0kNj7RpvBqDY+vRk0a8OY6iGB z$o_T+I+ZV>zz9OmpnHmp+}s=;1UYIuYHG?WYuTX-xRCfike!^-PD{lx(q@ouTZ#4 zDjOPEyQ8wal|Df@stR&zxmt5ozFsLfNJ~MU#lo7*d4)zWDRK&n!74M`58E6{^bNW? zx)y(|1Xn?UvApE3zYdN^PYnL$=k~$!UxLmd9zvSdF>nXNGyC!=c2S^(1nc$V>cw*Q@kl0U_{gLBZq1%8A^3_P6V4oBxPhXZCOo5PIc^PQ6CLR zf8gnBUtNmri#o*#IP%BMj?~UtWo?D6kqtW6NPJl5{gC@Jd2#o(Cs;YZ7kqghpjZ#T zS0N+-6j@#iU>S%n6wv{C1vMyQApED#Gb-Xx%Byb|LGWZVeu#05jK>8t8C~iI=dagO zf1E>`%E*kS*6delXFPS7JlJyRBla5cR>|NddJ`cZUJhtV;2reXAX+vked`#tzGTid z`l@h|NcQBkwt5=6Sak6!d97q{J&hWLdPRf1#tCsmpW~H64w2fF)#+_%>R@^H338tB z^gQ%5{=^7Nq(YQiXA`_fIhEw8<+#yi2mg@B-SUS}Za5|6?s=R!PoTLIAES1lTor}# zfk+3x9DILp(ICnn9RJH8vJJjI81yZFbtx4zl!eMxGW=fQiEJw9+ZU<7-9rUF2e0>` zgEt8D-ym>FOuB|i_MLg;~%zp#`t_?mwuWFG@+z~oQveS#)S&`I=|6lC8^(Ac9b zjPTSa5!7oVRD@_K@j(iHWyr`%a_GL_=$#z>_5&&hq4nGlS`Ev3c6h;PcvtAd@Gc={ zG@vW=VL+EC%~qpww3_g(d4d>0mPHAx5KZ(j_s;-^cJ)OP-v7byODp<^Ed&ahd784S3>B;tk)82lVeb_*Y^I8SsQD~RDD$e73? zHM@sEMZ#^xCPq&Pe&|X3lJn%TkCYe4zic?ak`-2rq!P*Xx}JV#JE$7#J7=COE$h5&>1y~x-4x)q5oRoiCp)=;`3`$LNM!VfvS>s@@ zz533sh@`X}Jp4d`YK?L_xw=w)(9Hk380XQlsuyLnj zM&tDa1^F-_F(z>|ATgCNnro^pTwE8fcNW+il}JH0R@&>F?2#V4x(4VU#`yyOv;>9l z%SC_~Ht0As4tE;$l}1{fk*P6O>Ve^)al)U3@xnOVXe=-oMU$e<=@j`c8jr>yUxE{Y z%jq^SBb)^;ux14@VI2As?s8SuIhAc0z=rh&MkDx}VOdep;GbdP0MhISvdoyci4k5T z5|T=LvpJ73*P95g^(=Kl??F!{7kA=V{zbYAH7R1vmEC&I*p6G8^6K2mwyHXZhjn$} z-St)F{q$8gwTW1BNV74CQ*Xy}GxCxXl`30;L(8`8$G5hhN`8-i-%ZJ%q-LV`7gJAC z=!$tYC6w6CFXioG(|rKf><(yb`2FV zM?f1v3E&}>froS=zYo9a@*cekg!O6kF^F?q0UIG|CAitQc%!cxShPd1D1^nthsc6^ zi0=Re+VwHoMaZoT+LCFepxs^QUmF0`b%!t$BSA*37%y1R@C`dw%kp7N5I?b7hRr>LhHVUAerY35<6 zJO=WQN85%P;1l%r5+-Ow2owuI#(83aQRmKoJ$@eaG49UF>5Qdg4FE!ntOM@-ZW)PM zg?I6criPROT09}a@#{e0x`$3~U}iBJ`JWe4vzX)j575s%Mvpd>WRBknE=OQn5iq&E zzR86%2P4$T^%!P96A<(@oa4Z!Q}S8N`r+kIK_P%9njap{xc%^O#y@5-!h&IX1EXjD zj*k5uPHlXO^n9$sV#}|tQM#PvZWcu)P_D%OR5s`~`mU?G@lfZW_7E@(| z-wmGl;k_TmXE3TkG;=WKZqSGsj{Qu7V?SB3T;e852giQ;;MmVPIQC;cz*!DZM;{*h z2@)_=!tbtNG*!$T;KwuHLtxfVWg_^t`IL|F5*Wbe!)_N-r#;{>2ig;Djp=WZuTYOM z@9_bla7pHIv6p{8%0M6E27~TQgFe2&FP+ak#&q-Q#mo{)c!s|oO2PFo|9%(~!CXcg zKouE!ZO}Fp#LuIIS;JTe74#4BybEMnKK#^T=0(QMKQo`2M!m-yLgA9k=lDwcn)o=F z3cB|O-#4F`Ms@Q)E{2Pn|873@4D<0`Y9_eZ_&cF+9ht@d2wm%7J`>xUcz2&@VnGjo zo6ZE?6Rr-Bv_Tz+hc z$rcw7e>g{%q>O9QpJ2O)8xVW&@Vo_5ie=@aM>cl-ilgaz2)7_CT_r8mT>;1}8c|K? zd?PyFEGa>g_&sQ{bT|rqpr|F$8sQ0u58ET`7M2Lpg*Cz&v_zPJcB6oQT=?_5><;4P z@THNV^pat$8B8ZehlwX}`|k*UtDg=sJ%frNT-C-JXha@WPtIwi;zknGNi! zf5LM$@lPQKudtNmS(KK;d7>@mH-ag;+Uj2Sa_CQ}4zF&gY;r5z1x?llRuEsjuGZ8g z)5#kBRtPZqlTe3Sa|*IDlo^#-)u5e=FSdHy^j)+VUr+(a(>WrY3Q<5%zR)tV7l*(g zxk6|rP&2HBNDk10=E+cS@|kE31qWmRO?4thsq@-`LsxUj2?N~(`z zzZPD?XA>y~wMOI8c5(oTebn>TX9?U=v<_mq^6G8OEwmADcUG0x(REctDkmqNlyR!6 zvy+smc{;O(T?)3@iiDm`ABlKcr_0mUW&q_`3}p=E!=*gU1J92Z^mtZ=B|Sr#Qu|QVDVr@VSskoUfbQdUxq6#{j!%e0oYWde=b8=|ngGPp+(9$%NWL9JBcMMl;wLNK{uF;#n7NJ+^b^;ineP&B zuf$)!q1bl?Z_QFUgNKRd}oT`8y7&xyWvXKNF8_R86CJguo6!a+VKPIYyH ziLsMBp4=J1E+^tu#RBRNHsMBaP^_m{;4dTX$vtM#>7)OqF@{db?=9{Ga zR=#vAD6s;)m4PrbP+uRTHWJ-$;FY!IH8sliv?fhXjwKy@$un_5`#8u&Vw2#H3x1C? zSBS*Tcz*8TT#HiGlGWDGSli-YUk4_VJquK8;w>=Bz(|pN&!3Qjo&fsmnik5zrzkx3 z=K3~ecY15G*;G^jnBD?m1D;~knN&(uy{Xg4^5TmEyQ9cXceS*3w`JCAAz0!AGzG5` zV>cewIDJSFVT6DLr}`AfuOUu2ydF5Da*z`yqaPLdr0{_-1=pH0bsA+-OInxRQC?|> ziqQtV(^>BTUzyI4;)JH*MWxwPZl;sd(~>mJIuFD)_#ERBv~>{826np@MJo0P!T3P~ z_(SQY#+qgu_d1$~BNv)I!jPp5&s=gdBfAT!HwpQ3)N{;!Y8|yrG$EqUObPlonkj{! zCRL41dCrf`5PnMeCWU1azk~SJ7^S_7p2}Phj z>2@(bIK3M!l|o>zU6EK>r8-6*t7`A5cW4(s8Pu?o4`bFwCX-@B3_g*!3^$Ef2pHs$GbCB6aJwtUrtg#x*a;WAix-h)#9>mCA6)xOgMvl(yHf9|} z7lUf^C8+QDgP+3gyMbma0K0J5mF?gt7Qew2VNHqPcjB*U@%Ni4Kw{ z)U5|ukd}MXwFkM8rKBnmPmawu0YKN3(OPXQE3aawkx4Dt9qi9UcTZz$3n#E}4D(YV zoLIRS$hm|cD7jvO6eTB02qB_`WZh34dN3xiWQ=T(8k7xIj2Q#pvBOalP6s_aH@+JF zw~;OIzlxlO|FPq3_}>ve#=ew{m5h@pBvU0XNi33gCBI5W{4l?neqnx3`K|Ix^0WCh zNFRff;yu#S(yygIN`LW}`j7R0+CSDm#Xr|S-@nY?<~uXq>wm=mlK)ja0DlzUg73i( z;c7e`ci^w#|0ZzaQQ{Ti5FC2xAkGk<65kSkBLw0BNs?p8N68iBMsgb&MJAJ4(m|eu z)8hBYUjxPkJQ^@9;HiL@0yYHf^qmh^2V?~p0?Yx218f0~fR=!sfPsLM0T%;44EQwQ ztAM`+{4>x$P#zc*I0;UQ&k0-<_gA=z_0^5wvhd`ATS7LMS_Q{i0h|k_WFjuPoZ)2W z6BGN^)9VxC_at(Qghw-z&2V^pa%q%3y*WAHtG5;THTg9TrK73_&N|;kkKy%pTU`s? zV$_3UPBs;kBN08Cco($~N~bfjg$yX` zG6Ih9si!fO z5cr}3;3AV=#tUkzifd?3liO2oap|i$VZvv4jV=cc?did92_YF1R^WQ8#Q+FsQ--Ie zsuU1VxuUed4Cl7fb4)4=mlKX3&MUU&D^o$RG}YC1)UwqrD19$pTnVTj-O}J_ui+Z5 z;AOVb>MCUih?XpUZfY)TO~>WruG+Zc32aJ#cfl$87SUZ=;%evK@55Ea5adtyxH>w( zkuM{Yok>TIIJ>*x;N2V;t|33ypjWCJ)b1)81Ew>1;{{F^ZKnnZQ zR##u$XlG@L3ahm=9}Y04q-Iy>;an}+zZySWWrOqS?gpX0jbiYh;$sm3bw)C8|pB&QAWpxm8dw*`%eNR>b-OCy6e5S)_ci1`WucCIwO1KwPHXn|P74TNfr6=Q-eapXJms;}K?3pu zIy&;2o1uZMCsV`ob)Z62DV+@soos10wKKSZ#~MGK)G5PjV<{}d*5w|qb;EEcCM>OK==W5cc9lH zZz|6>EhK>L7nl;_&On}kGHO#xUPq@OHx#t3D6z2xaByfv7o4?ADX3sb5o$$Y0UXsk z)&*ySDheu?QX4qbGnL{Tnd$4np1+*zE=UPk&QJkG=z7?Ytt!oLfJ`C-tu(3M038;0 zVHmr)xB7A``!}frxxB5gWfxI)(cvQAJA z7Sw>cuhb0WxN(%@QZI7Z<}GF0nT?Zaew0NXp}b`F?4c_1kO|~W6EtgwL_@`7*qlrO zo>CUGqY8A4U_0DTx}IEGmQzp(pcj=H1#4l#g*lZZCly9BL*ip15^_`EFav_Aoqb%6 zNY@K=Qc7Sqj|tm(g(d7j9r|YRx@-wEA~rfAVM}5uocjmXCD~e*4$~pX5FCjH)>fLo zr35x=Vyhw~>oQ@ZW(Zgy^cLBwv-C0u2eYL8^K?|Gx-Mj0N~BL7sKL@pi?WIf*!hK7 zTZ$RGs3lqXsfDZ(adOsLrYj{rB`Z==cG}W;icV;&3XS}nb-Vz+QX=Ii7$7lI75sD}x*$=1{U>C3%EFMXg zX(hqBmRwkRKNAy_5PUSKj>}IaBJY+1I02=uuBft+ee)n0p){7I3q#9e8``$kHMK^! zhgY*}Ljv;!%preDU}RQYC|ej6E95i$K_ePF#%c9Lx(3vQCxD1HMF$}VX6Fa|$lSeo zXA8!1zed?s zvT18M>}PE(uVx?vDKrEQ8h~UD=R`ONz%G=ww#Alsvyn6!5rl#w*sLr9BoLYI3m$2v zmBOG+QyEcQ!;wb{a4y>`(^igp*_VsbQWBp8_P4952Z(P6P~*^vwl~)5r^I zQFcyA39G0mH)ksok>(CaN!T0!10ETJ!0~D_A{7qM5$chQcCTHm7QcWzcTn%I0!2Fs z4cS>-O z(+TD5qidk+BT&NE2&^E0u0I|t;R3vL?mHzSSo|s=HyB_*ICLCj$T1o)0_X^!4_*ZH zFC1PMaLnT1fBt=EwZO(Kut@OU7vlvehSB1VDE>#m%u#-@?Z+sY)OF8mIZi(aq!;)C}H~` zr+nN&ct;leodLN}8$$2GBanI#t^-#G*loK2f9(bCy39=vd`kf{5zA>kApbQ3^4s@t zUjXQa0f4O-F1x}3X)z4m-vqf-0_3+Sz&p%``$+k|t&b6(e|G=6baHz$pb%C=KK`+< z+|>!-*fznNmqWfo0cEijFd1C{7mg2ZZt!;oB(;TrfA}lzKH#N=12$qfUK7H~a`FcX zvG+hd
    ugPT0;eF(h=P}ZPv;GzMx;~Xt>zak*J0U{+2@X2s1Wu}KukkAk3D>H+9MLa%EBr{_}MLr?8B$=5O zfrZbMnVSLWECN?3Gs`eEGF-LH+#!3nJdc3eC(A4LR_sY`%3b9qmNN`#4l^mEOtS1* zZepduL!K1?Ig%pu_iGxj$g&$-)8hr2PJB`2GRn z8bVwpXr)c?b`?P5)RW=dSp&8mNru%qM)t%9)K1wGo+x{wKr9T&6T4%6aF_XDX=nnD zrvYGfS^(}K7D^ou2(dd|X6Fyv`EonNlKI1(4xtnvoED%J%EM!KEF9cr{&+wP#6uVY zyiW=6^$1V{ufSXamk2I6fC*+8wC`)&8{FGrdkEM+0HsKA?{M!Seh|#Z31BM9T<;Hu zeJ=}*hu%a0iqU}5V>p}D5Q_katnVNmR`Rjn1K1cqj~L47JPaBdQkUbIj@T41x&owA zjx6LDFcl%s%CguP?kQ(D9$+d%D6C~MT1J68jHYFVtPOEM%b5QN{bKJXLOlYB~(e6PT;hZfX8zYRFOh9QXvu;WE{$)(2OW}5?*3S zz>}(+(G}>_Q7+omtQ2hkY{mY|04OyA7z74Si@_Jq#{Q`8sKiJb2X$i~zJAKTml~%# ztuB^IDauJRsgjIafJ%t*sD$8MMI_(}1T`!D>mT0n+A7{`erV9yyXqRM{8v`-WXP1W zERV$RNfdR$_s-mLD4hZpnz{-=LJOURej!sanCWR;BXkPpK~&cp@!+@!g8_>=k{28% z4DsVQ1LCxhFNomS*`lm*%BUr3!8HdEY51)gr_410tC@+Z`3&I;@`Vm>Zap``X;a z&HV8t3lHxlPAkm9k0$u)Y&dz#uqS{vXnC_ZGIubqwY@XC@MVJof5F0Ofk@s`N2BcL zZVp*jsSg-a-$@$XZl0U>+W2tP?Tt+*HtCcGEmkOC-R>LkyC*uj=xBwP^}SyYYS!>$ zg&GMh#sne|QH{6<6(2#(C<;IiWHJ?xCrw5T(1{~<6rZj&41*oYj|iI<4NVaN1;jA2 zQ6;Dm9d$hZPZ9x8piMCwn=}4nR836R8;-~q1$_~3I;g)G^Lf+29o57l>0?PK zp|p{g5*1Jt%v}|8ClLvh!zc^0k0Aj~)T*OnxT;XCG7_M;INNfKO-9!;kP=Y>!};=K zjwdIk+1{L3nx0wu zq>HLMXTGf>wNs!yvCIC-{FEo#E}SBCXk2hPp;?o%=6&33cTwW{aTQbTs!uzgPqY~{ zoVj<|7F=C0E!F+Khw~e)U9PHOKMlQYDX3Bzce_V3#p{%+QAj%J<&!tDlP-~uJvUqJ zv2T&dD^uuwJ#ZNh_r8UP#uwb#==7bPv@h6RnOpl+m7(ISQ9WUmEtig}V^yr6uH*{n zpaM|{$Bq{!;A)^_F=wheGCxY>%?pVZ1_cR5+JmM}aq;KHL<+b%C=&~YsB6d_ICcVn zKlK&zWk{!7HmW0UKh0rptOElWyS)DncUx2Fsb-(MEoL9+qPyh4K48(k|{ca`8( zai|1OBVZKOaQesEv*$Q%w8Ra~8Bs4fmcG1mMD>s#ue-)a`{x7iPn$NSp&Q(ivikyW zSyZSVy7V;mRm}FJQ0qhaZOZ%o-vn(r-R)%DWN-6!_ceD1OzLr@Fa@Mjf(lG{|s2twy)5OndBdgcj2C>6pWBelQ%x+?GohnMZJ|f3eL5zk8XXwU-|We zB{!>v{Ht0uX6?#2a$uNa^r7M#{~^b~Xh+U56i^EEZUP>M+G1{O(oEC}wWuOcI$xW+A+E%z@Q|b#->bd&TzjTl$Q^|#H6ABV=c_*?IVle;oHQM0)&AgA z{?gK`dfs&D982A0Vce9LSymal9z80;eY)^{;nInh8zwD{Z{5SQeQkLD;i;P*w+ zNXX|b7Xiw#DDF$fz_FF56&Z((pXRdB+k(pl(vbaN^ft9XEx8sWY~cS@VgD8TX`85^ zFeTo+!b_>~q2sKjzpU-DUZ8!z=oMrc3bXI z(?vJz_yJCimvbJ4typqtgD~Ml*x;^T#zyufxI3=AQh10Sv#tG2wf?I%?L0rN{x=lT zz~+4qa1U>U3mVgDQJ=XbN7SY|zabG`Z1;0v3!TT!{D<8`#>o{5||UN`@y#;0aO zrxQ8XNQ)k9BH>jM^xN~s$!j4CVG%jA~2FK1qSHt!6U*1UWvp*J-4}6tww)9UD59~6@l*j z1k?S5z97c3QR=W%Ow!2dzrsjw-nc37rwb_oSM9Z?CXAnk>T6CIW=BDxexYB=G0_n+ zH!LM=IMY!fX_7ROuL$ao-gR^n4zo>!+$LDWMx^(o!bC-l{3jh}zn zHl8eWa9ieeI!OX(dX4(yW_0!?KTH!C7G!p(-}Vq|rW&iAz5T}yiDB?$wldPw|BzuY z{@$B0p=zB4A0N&moAjM8U*R!%cg4CZs|V^57t9rH+M^PvLK!kOw-4W2J}Ik5;HjJ* zT{b^{uwc!gyNQBnt;=q$IsR*2&2w01<&x@o>Cx0z&0~6ZJmUwT60#<+wNJxrjo#l( zvk&8kZ<_J56Urd1|Awt~{CBanS?CNoTQhMHh~U#Tp}sP<#f#)%4IMH3C798I?sQQY zj{`iAi^A7urpo!6{x^KhF4PC+ARrrKQxFUkeR%o-u}r?0et`9_>4*5%m&F3%7E512 zoo2@i68eUULWDf-7#X>P%%$MW3*k6~MhLhQP+cq>O@r~zzr(}TMj5h_YN#&?fu!Up z^CO?^;m$^_Wxnd>^M!uGNL~_v<^= zCu-f5XL`*UE2kd6c1b;OrbqR6d09pAJKQ(s>-Yb(VC9~}sy{ZXN?Kj$=jZP>GF-J$ zRWwwevba}hXz^y#qppedom)%hw8uJd`Q{(yv3q%rMGprTyB`tC`H2Ld00LeNOlUEV zBAdy4G5MgTpmQ-VHfaV-B+aW#tGMaYMGt?^_|yS)91)u=jc_UgUQ_$;NKht_eu_u(JF~ z@<+3$)+OBIsXmHEM_EhLud#F9Zcz`&a`88tVmC!aBjVx7}b$i5@oQg2yPmXLC{@vKCVWguBmZ8??ClS{kY)wi$ za_c?0i)mjbe0aFl+S(R3`%Yp1u?Jhid%wq@z!^BqweH+z(4bTwoU&=Ne!_)AbF`mK zFZ|G-5p%qA<&W{RTu^7`9dENgS(o0d%AdThfAP4bNvr>;%`Zv5b8etEYG8mqxbWe- z@uC~k%oy7{>K7+XS54jgk6+MYrJ=_(jZl^XP z11(wZxX9SV7!LenA!TClKO7fE4;=rloV-%+H?!Iv-WmIS_?DGBd{l2{=k^>ptJL2T zU!|9PXQ7pYanPmYaK_rFVGTQ9EPJ4;-$Kg-|mep1)@ zsKlAyHdc9g#u%oJi&J6d)H0hqhC(TM+KK!+``jyB32_t1$(aN^9u=QL#s4Q6AVKXL z`Tp~6M3uN02v2c%Lt-+XOC`d}3+!j0XW!!?sUH|K*M5iL$~O1AFPJ>^h%)yjpuQVa0=O5_~c+$%N0Dr*I|sAaL@>D8%o7WEbTh z?A?rNK6g~>b8d)Sq56v{P8>L9*s>0?A7nXFnTuYM~sL85tnjo-z&DO?vb7Q>7 z@L-R^i?*{=?%Z#iz&~HL(Mq}LMc28FRm4HjzG++g`d&TT$vpkc;r3;pt`4(a^^7r& zx<@YFV7132%r{;=<&b;#^X9|>Ikk5AeKTQN(=b!!b@rnq^zg@ok$PDirhvp^dmsloUI1`h3qu&oG^S=OMw~^-n diff --git a/hacks/fonts/gallant12x22-bsd.c b/hacks/fonts/gallant12x22-bsd.c new file mode 100644 index 000000000..1af343c52 --- /dev/null +++ b/hacks/fonts/gallant12x22-bsd.c @@ -0,0 +1,6198 @@ +/* http://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/dev/wsfont/gallant12x22.h */ +/* $NetBSD: gallant12x22.h,v 1.11 2005/12/11 12:24:12 christos Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory and to the University + * of California at Berkeley by Jef Poskanzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Derived from: @(#)gallant19.h 8.1 (Berkeley) 6/11/93 + */ + +static u_char gallant12x22_data[]; + +static struct wsdisplay_font gallant12x22 = { + "Gallant", /* typeface name */ + 0, /* firstchar */ + 255 - 0 + 1, /* numchar */ + WSDISPLAY_FONTENC_ISO, /* encoding */ + 12, /* width */ + 22, /* height */ + 2, /* stride */ + WSDISPLAY_FONTORDER_L2R, /* bit order */ + WSDISPLAY_FONTORDER_L2R, /* byte order */ + gallant12x22_data /* data */ +}; + +static u_char gallant12x22_data[] = { + /* 0 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 1 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x1f, 0x80, /* ...******... */ + 0x3f, 0xc0, /* ..********.. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x3f, 0xc0, /* ..********.. */ + 0x1f, 0x80, /* ...******... */ + 0x0f, 0x00, /* ....****.... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 2 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x55, 0x40, /* .*.*.*.*.*.. */ + 0x2a, 0xa0, /* ..*.*.*.*.*. */ + 0x55, 0x40, /* .*.*.*.*.*.. */ + 0x2a, 0xa0, /* ..*.*.*.*.*. */ + 0x55, 0x40, /* .*.*.*.*.*.. */ + 0x2a, 0xa0, /* ..*.*.*.*.*. */ + 0x55, 0x40, /* .*.*.*.*.*.. */ + 0x2a, 0xa0, /* ..*.*.*.*.*. */ + 0x55, 0x40, /* .*.*.*.*.*.. */ + 0x2a, 0xa0, /* ..*.*.*.*.*. */ + 0x55, 0x40, /* .*.*.*.*.*.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 3 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x44, 0x00, /* .*...*...... */ + 0x44, 0x00, /* .*...*...... */ + 0x44, 0x00, /* .*...*...... */ + 0x7c, 0x00, /* .*****...... */ + 0x44, 0x00, /* .*...*...... */ + 0x44, 0x00, /* .*...*...... */ + 0x44, 0x00, /* .*...*...... */ + 0x03, 0xe0, /* ......*****. */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 4 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7c, 0x00, /* .*****...... */ + 0x40, 0x00, /* .*.......... */ + 0x40, 0x00, /* .*.......... */ + 0x78, 0x00, /* .****....... */ + 0x40, 0x00, /* .*.......... */ + 0x40, 0x00, /* .*.......... */ + 0x40, 0x00, /* .*.......... */ + 0x03, 0xe0, /* ......*****. */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x03, 0xc0, /* ......****.. */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 5 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x38, 0x00, /* ..***....... */ + 0x44, 0x00, /* .*...*...... */ + 0x40, 0x00, /* .*.......... */ + 0x40, 0x00, /* .*.......... */ + 0x40, 0x00, /* .*.......... */ + 0x44, 0x00, /* .*...*...... */ + 0x38, 0x00, /* ..***....... */ + 0x03, 0xc0, /* ......****.. */ + 0x02, 0x20, /* ......*...*. */ + 0x02, 0x20, /* ......*...*. */ + 0x03, 0xc0, /* ......****.. */ + 0x02, 0x80, /* ......*.*... */ + 0x02, 0x40, /* ......*..*.. */ + 0x02, 0x20, /* ......*...*. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 6 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x40, 0x00, /* .*.......... */ + 0x40, 0x00, /* .*.......... */ + 0x40, 0x00, /* .*.......... */ + 0x40, 0x00, /* .*.......... */ + 0x40, 0x00, /* .*.......... */ + 0x40, 0x00, /* .*.......... */ + 0x7c, 0x00, /* .*****...... */ + 0x03, 0xe0, /* ......*****. */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x03, 0xc0, /* ......****.. */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 7 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0e, 0x00, /* ....***..... */ + 0x17, 0x00, /* ...*.***.... */ + 0x23, 0x80, /* ..*...***... */ + 0x61, 0x80, /* .**....**... */ + 0x61, 0x80, /* .**....**... */ + 0x71, 0x00, /* .***...*.... */ + 0x3a, 0x00, /* ..***.*..... */ + 0x1c, 0x00, /* ...***...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 8 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 9 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x44, 0x00, /* .*...*...... */ + 0x64, 0x00, /* .**..*...... */ + 0x64, 0x00, /* .**..*...... */ + 0x54, 0x00, /* .*.*.*...... */ + 0x4c, 0x00, /* .*..**...... */ + 0x4c, 0x00, /* .*..**...... */ + 0x44, 0x00, /* .*...*...... */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x03, 0xe0, /* ......*****. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 10 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x44, 0x00, /* .*...*...... */ + 0x44, 0x00, /* .*...*...... */ + 0x44, 0x00, /* .*...*...... */ + 0x28, 0x00, /* ..*.*....... */ + 0x28, 0x00, /* ..*.*....... */ + 0x10, 0x00, /* ...*........ */ + 0x10, 0x00, /* ...*........ */ + 0x03, 0xe0, /* ......*****. */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 11 */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0xfe, 0x00, /* *******..... */ + 0xfe, 0x00, /* *******..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 12 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xfe, 0x00, /* *******..... */ + 0xfe, 0x00, /* *******..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + + /* 13 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x07, 0xf0, /* .....******* */ + 0x07, 0xf0, /* .....******* */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + + /* 14 */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x07, 0xf0, /* .....******* */ + 0x07, 0xf0, /* .....******* */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 15 */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0xff, 0xf0, /* ************ */ + 0xff, 0xf0, /* ************ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + + /* 16 */ + 0x00, 0x00, /* ............ */ + 0xff, 0xf0, /* ************ */ + 0xff, 0xf0, /* ************ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 17 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xff, 0xf0, /* ************ */ + 0xff, 0xf0, /* ************ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 18 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xff, 0xf0, /* ************ */ + 0xff, 0xf0, /* ************ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 19 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xff, 0xf0, /* ************ */ + 0xff, 0xf0, /* ************ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 20 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xff, 0xf0, /* ************ */ + 0xff, 0xf0, /* ************ */ + 0x00, 0x00, /* ............ */ + + /* 21 */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x07, 0xf0, /* .....******* */ + 0x07, 0xf0, /* .....******* */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + + /* 22 */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0xfe, 0x00, /* *******..... */ + 0xfe, 0x00, /* *******..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + + /* 23 */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0xff, 0xf0, /* ************ */ + 0xff, 0xf0, /* ************ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 24 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xff, 0xf0, /* ************ */ + 0xff, 0xf0, /* ************ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + + /* 25 */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + + /* 26 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0xe0, /* ........***. */ + 0x07, 0x80, /* .....****... */ + 0x1e, 0x00, /* ...****..... */ + 0x78, 0x00, /* .****....... */ + 0x78, 0x00, /* .****....... */ + 0x1e, 0x00, /* ...****..... */ + 0x07, 0x80, /* .....****... */ + 0x00, 0xe0, /* ........***. */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 27 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x70, 0x00, /* .***........ */ + 0x1e, 0x00, /* ...****..... */ + 0x07, 0x80, /* .....****... */ + 0x01, 0xe0, /* .......****. */ + 0x01, 0xe0, /* .......****. */ + 0x07, 0x80, /* .....****... */ + 0x1e, 0x00, /* ...****..... */ + 0x70, 0x00, /* .***........ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 28 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x3f, 0xe0, /* ..*********. */ + 0x7f, 0xc0, /* .*********.. */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x31, 0x80, /* ..**...**... */ + 0x31, 0x80, /* ..**...**... */ + 0x31, 0xc0, /* ..**...***.. */ + 0x60, 0xc0, /* .**.....**.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 29 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x40, /* .........*.. */ + 0x00, 0xc0, /* ........**.. */ + 0x01, 0x80, /* .......**... */ + 0x7f, 0xc0, /* .*********.. */ + 0x7f, 0xc0, /* .*********.. */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x7f, 0xc0, /* .*********.. */ + 0x7f, 0xc0, /* .*********.. */ + 0x30, 0x00, /* ..**........ */ + 0x60, 0x00, /* .**......... */ + 0x40, 0x00, /* .*.......... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 30 */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x10, 0x00, /* ...*........ */ + 0x10, 0x00, /* ...*........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x3e, 0x00, /* ..*****..... */ + 0x7c, 0x00, /* .*****...... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x3f, 0x20, /* ..******..*. */ + 0x3f, 0xe0, /* ..*********. */ + 0x31, 0xc0, /* ..**...***.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 31 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 32 ( ) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 33 (!) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 34 (") */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 35 (#) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x03, 0x30, /* ......**..** */ + 0x03, 0x30, /* ......**..** */ + 0x03, 0x30, /* ......**..** */ + 0x06, 0x60, /* .....**..**. */ + 0x1f, 0xf0, /* ...********* */ + 0x1f, 0xf0, /* ...********* */ + 0x0c, 0xc0, /* ....**..**.. */ + 0x0c, 0xc0, /* ....**..**.. */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x7f, 0xc0, /* .*********.. */ + 0x7f, 0xc0, /* .*********.. */ + 0x33, 0x00, /* ..**..**.... */ + 0x66, 0x00, /* .**..**..... */ + 0x66, 0x00, /* .**..**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 36 ($) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x3f, 0xc0, /* ..********.. */ + 0x66, 0xe0, /* .**..**.***. */ + 0x66, 0x60, /* .**..**..**. */ + 0x66, 0x00, /* .**..**..... */ + 0x3e, 0x00, /* ..*****..... */ + 0x1f, 0x80, /* ...******... */ + 0x07, 0xc0, /* .....*****.. */ + 0x06, 0x60, /* .....**..**. */ + 0x06, 0x60, /* .....**..**. */ + 0x66, 0x60, /* .**..**..**. */ + 0x7f, 0xc0, /* .*********.. */ + 0x3f, 0x80, /* ..*******... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 37 (%) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x38, 0x60, /* ..***....**. */ + 0x44, 0xc0, /* .*...*..**.. */ + 0x44, 0xc0, /* .*...*..**.. */ + 0x45, 0x80, /* .*...*.**... */ + 0x39, 0x80, /* ..***..**... */ + 0x03, 0x00, /* ......**.... */ + 0x03, 0x00, /* ......**.... */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x19, 0xc0, /* ...**..***.. */ + 0x1a, 0x20, /* ...**.*...*. */ + 0x32, 0x20, /* ..**..*...*. */ + 0x32, 0x20, /* ..**..*...*. */ + 0x61, 0xc0, /* .**....***.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 38 (&) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x07, 0x00, /* .....***.... */ + 0x0f, 0x80, /* ....*****... */ + 0x18, 0xc0, /* ...**...**.. */ + 0x18, 0xc0, /* ...**...**.. */ + 0x18, 0xc0, /* ...**...**.. */ + 0x0f, 0x80, /* ....*****... */ + 0x1e, 0x00, /* ...****..... */ + 0x3e, 0x00, /* ..*****..... */ + 0x77, 0x00, /* .***.***.... */ + 0x63, 0x60, /* .**...**.**. */ + 0x61, 0xe0, /* .**....****. */ + 0x61, 0xc0, /* .**....***.. */ + 0x61, 0x80, /* .**....**... */ + 0x3f, 0xe0, /* ..*********. */ + 0x1e, 0x60, /* ...****..**. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 39 (') */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0c, 0x00, /* ....**...... */ + 0x1e, 0x00, /* ...****..... */ + 0x1e, 0x00, /* ...****..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x00, /* ...**....... */ + 0x10, 0x00, /* ...*........ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 40 (() */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0xc0, /* ........**.. */ + 0x01, 0x80, /* .......**... */ + 0x03, 0x80, /* ......***... */ + 0x03, 0x00, /* ......**.... */ + 0x07, 0x00, /* .....***.... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x07, 0x00, /* .....***.... */ + 0x03, 0x00, /* ......**.... */ + 0x03, 0x80, /* ......***... */ + 0x01, 0x80, /* .......**... */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 41 ()) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x30, 0x00, /* ..**........ */ + 0x18, 0x00, /* ...**....... */ + 0x1c, 0x00, /* ...***...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0e, 0x00, /* ....***..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0e, 0x00, /* ....***..... */ + 0x0c, 0x00, /* ....**...... */ + 0x1c, 0x00, /* ...***...... */ + 0x18, 0x00, /* ...**....... */ + 0x30, 0x00, /* ..**........ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 42 (*) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x06, 0x00, /* .....**..... */ + 0x66, 0x60, /* .**..**..**. */ + 0x76, 0xe0, /* .***.**.***. */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x19, 0x80, /* ...**..**... */ + 0x76, 0xe0, /* .***.**.***. */ + 0x66, 0x60, /* .**..**..**. */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 43 (+) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 44 (,) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0c, 0x00, /* ....**...... */ + 0x1e, 0x00, /* ...****..... */ + 0x1e, 0x00, /* ...****..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x00, /* ...**....... */ + 0x10, 0x00, /* ...*........ */ + + /* 45 (-) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 46 (.) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0c, 0x00, /* ....**...... */ + 0x1e, 0x00, /* ...****..... */ + 0x1e, 0x00, /* ...****..... */ + 0x0c, 0x00, /* ....**...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 47 (/) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x60, /* .........**. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x01, 0x80, /* .......**... */ + 0x01, 0x80, /* .......**... */ + 0x03, 0x00, /* ......**.... */ + 0x03, 0x00, /* ......**.... */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x60, 0x00, /* .**......... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 48 (0) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x07, 0x00, /* .....***.... */ + 0x0f, 0x80, /* ....*****... */ + 0x11, 0x80, /* ...*...**... */ + 0x10, 0xc0, /* ...*....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0x80, /* ..**....*... */ + 0x18, 0x80, /* ...**...*... */ + 0x1f, 0x00, /* ...*****.... */ + 0x0e, 0x00, /* ....***..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 49 (1) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x02, 0x00, /* ......*..... */ + 0x06, 0x00, /* .....**..... */ + 0x0e, 0x00, /* ....***..... */ + 0x1e, 0x00, /* ...****..... */ + 0x36, 0x00, /* ..**.**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x3f, 0xc0, /* ..********.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 50 (2) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0x00, /* ...*****.... */ + 0x3f, 0x80, /* ..*******... */ + 0x61, 0xc0, /* .**....***.. */ + 0x40, 0xc0, /* .*......**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x01, 0x80, /* .......**... */ + 0x03, 0x00, /* ......**.... */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x00, /* ...**....... */ + 0x30, 0x20, /* ..**......*. */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 51 (3) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x1f, 0xc0, /* ...*******.. */ + 0x20, 0xe0, /* ..*.....***. */ + 0x40, 0x60, /* .*.......**. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0xe0, /* ........***. */ + 0x07, 0xc0, /* .....*****.. */ + 0x0f, 0xc0, /* ....******.. */ + 0x00, 0xe0, /* ........***. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x60, /* .........**. */ + 0x40, 0x60, /* .*.......**. */ + 0x60, 0x40, /* .**......*.. */ + 0x3f, 0x80, /* ..*******... */ + 0x1f, 0x00, /* ...*****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 52 (4) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x01, 0x80, /* .......**... */ + 0x03, 0x80, /* ......***... */ + 0x03, 0x80, /* ......***... */ + 0x05, 0x80, /* .....*.**... */ + 0x05, 0x80, /* .....*.**... */ + 0x09, 0x80, /* ....*..**... */ + 0x09, 0x80, /* ....*..**... */ + 0x11, 0x80, /* ...*...**... */ + 0x11, 0x80, /* ...*...**... */ + 0x21, 0x80, /* ..*....**... */ + 0x3f, 0xe0, /* ..*********. */ + 0x7f, 0xe0, /* .**********. */ + 0x01, 0x80, /* .......**... */ + 0x01, 0x80, /* .......**... */ + 0x01, 0x80, /* .......**... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 53 (5) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0xc0, /* ....******.. */ + 0x0f, 0xc0, /* ....******.. */ + 0x10, 0x00, /* ...*........ */ + 0x10, 0x00, /* ...*........ */ + 0x20, 0x00, /* ..*......... */ + 0x3f, 0x80, /* ..*******... */ + 0x31, 0xc0, /* ..**...***.. */ + 0x00, 0xe0, /* ........***. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x60, /* .........**. */ + 0x40, 0x60, /* .*.......**. */ + 0x60, 0x60, /* .**......**. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 54 (6) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x07, 0x00, /* .....***.... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x00, /* ...**....... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x60, 0x00, /* .**......... */ + 0x67, 0x80, /* .**..****... */ + 0x6f, 0xc0, /* .**.******.. */ + 0x70, 0xe0, /* .***....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0x40, /* .***.....*.. */ + 0x3f, 0x80, /* ..*******... */ + 0x1f, 0x00, /* ...*****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 55 (7) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0xe0, /* ...********. */ + 0x3f, 0xe0, /* ..*********. */ + 0x60, 0x40, /* .**......*.. */ + 0x00, 0x40, /* .........*.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0x80, /* ........*... */ + 0x00, 0x80, /* ........*... */ + 0x01, 0x80, /* .......**... */ + 0x01, 0x00, /* .......*.... */ + 0x01, 0x00, /* .......*.... */ + 0x03, 0x00, /* ......**.... */ + 0x02, 0x00, /* ......*..... */ + 0x02, 0x00, /* ......*..... */ + 0x06, 0x00, /* .....**..... */ + 0x04, 0x00, /* .....*...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 56 (8) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x11, 0x80, /* ...*...**... */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x18, 0x80, /* ...**...*... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x06, 0x00, /* .....**..... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x11, 0x80, /* ...*...**... */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x18, 0x80, /* ...**...*... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 57 (9) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xe0, /* ..*.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0xe0, /* .***....***. */ + 0x3f, 0x60, /* ..******.**. */ + 0x1e, 0x60, /* ...****..**. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x01, 0x80, /* .......**... */ + 0x07, 0x00, /* .....***.... */ + 0x3c, 0x00, /* ..****...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 58 (:) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0c, 0x00, /* ....**...... */ + 0x1e, 0x00, /* ...****..... */ + 0x1e, 0x00, /* ...****..... */ + 0x0c, 0x00, /* ....**...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0c, 0x00, /* ....**...... */ + 0x1e, 0x00, /* ...****..... */ + 0x1e, 0x00, /* ...****..... */ + 0x0c, 0x00, /* ....**...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 59 (;) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0c, 0x00, /* ....**...... */ + 0x1e, 0x00, /* ...****..... */ + 0x1e, 0x00, /* ...****..... */ + 0x0c, 0x00, /* ....**...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0c, 0x00, /* ....**...... */ + 0x1e, 0x00, /* ...****..... */ + 0x1e, 0x00, /* ...****..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x00, /* ...**....... */ + 0x10, 0x00, /* ...*........ */ + + /* 60 (<) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x60, /* .........**. */ + 0x01, 0xc0, /* .......***.. */ + 0x07, 0x00, /* .....***.... */ + 0x1e, 0x00, /* ...****..... */ + 0x78, 0x00, /* .****....... */ + 0x78, 0x00, /* .****....... */ + 0x1e, 0x00, /* ...****..... */ + 0x07, 0x00, /* .....***.... */ + 0x01, 0xc0, /* .......***.. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 61 (=) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xc0, /* .*********.. */ + 0x7f, 0xc0, /* .*********.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xc0, /* .*********.. */ + 0x7f, 0xc0, /* .*********.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 62 (>) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x60, 0x00, /* .**......... */ + 0x38, 0x00, /* ..***....... */ + 0x1e, 0x00, /* ...****..... */ + 0x07, 0x80, /* .....****... */ + 0x01, 0xe0, /* .......****. */ + 0x01, 0xe0, /* .......****. */ + 0x07, 0x80, /* .....****... */ + 0x1e, 0x00, /* ...****..... */ + 0x38, 0x00, /* ..***....... */ + 0x60, 0x00, /* .**......... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 63 (?) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x1f, 0x80, /* ...******... */ + 0x39, 0xc0, /* ..***..***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x01, 0x80, /* .......**... */ + 0x03, 0x00, /* ......**.... */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 64 (@) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x3f, 0xc0, /* ..********.. */ + 0x30, 0x60, /* ..**.....**. */ + 0x60, 0x60, /* .**......**. */ + 0x67, 0x20, /* .**..***..*. */ + 0x6f, 0xa0, /* .**.*****.*. */ + 0x6c, 0xa0, /* .**.**..*.*. */ + 0x6c, 0xa0, /* .**.**..*.*. */ + 0x67, 0xe0, /* .**..******. */ + 0x60, 0x00, /* .**......... */ + 0x30, 0x00, /* ..**........ */ + 0x3f, 0xe0, /* ..*********. */ + 0x0f, 0xe0, /* ....*******. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 65 (A) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x09, 0x00, /* ....*..*.... */ + 0x11, 0x80, /* ...*...**... */ + 0x11, 0x80, /* ...*...**... */ + 0x10, 0x80, /* ...*....*... */ + 0x3f, 0xc0, /* ..********.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x40, /* ..*......*.. */ + 0x40, 0x60, /* .*.......**. */ + 0x40, 0x60, /* .*.......**. */ + 0xe0, 0xf0, /* ***.....**** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 66 (B) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xff, 0x00, /* ********.... */ + 0x60, 0x80, /* .**.....*... */ + 0x60, 0xc0, /* .**.....**.. */ + 0x60, 0xc0, /* .**.....**.. */ + 0x60, 0xc0, /* .**.....**.. */ + 0x61, 0x80, /* .**....**... */ + 0x7f, 0x80, /* .********... */ + 0x60, 0xc0, /* .**.....**.. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0xc0, /* .**.....**.. */ + 0xff, 0x80, /* *********... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 67 (C) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0xc0, /* ....******.. */ + 0x10, 0x60, /* ...*.....**. */ + 0x20, 0x20, /* ..*.......*. */ + 0x20, 0x00, /* ..*......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x20, 0x00, /* ..*......... */ + 0x30, 0x20, /* ..**......*. */ + 0x18, 0x40, /* ...**....*.. */ + 0x0f, 0x80, /* ....*****... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 68 (D) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xff, 0x00, /* ********.... */ + 0x61, 0xc0, /* .**....***.. */ + 0x60, 0xc0, /* .**.....**.. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x40, /* .**......*.. */ + 0x61, 0x80, /* .**....**... */ + 0xfe, 0x00, /* *******..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 69 (E) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xc0, /* .*********.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x80, /* ..**....*... */ + 0x3f, 0x80, /* ..*******... */ + 0x30, 0x80, /* ..**....*... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x20, /* ..**......*. */ + 0x30, 0x20, /* ..**......*. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 70 (F) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xc0, /* .*********.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x80, /* ..**....*... */ + 0x3f, 0x80, /* ..*******... */ + 0x30, 0x80, /* ..**....*... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x78, 0x00, /* .****....... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 71 (G) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0xc0, /* ....******.. */ + 0x10, 0x60, /* ...*.....**. */ + 0x20, 0x20, /* ..*.......*. */ + 0x20, 0x00, /* ..*......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x61, 0xf0, /* .**....***** */ + 0x60, 0x60, /* .**......**. */ + 0x20, 0x60, /* ..*......**. */ + 0x30, 0x60, /* ..**.....**. */ + 0x18, 0x60, /* ...**....**. */ + 0x0f, 0x80, /* ....*****... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 72 (H) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xf0, 0xf0, /* ****....**** */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x7f, 0xe0, /* .**********. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0xf0, 0xf0, /* ****....**** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 73 (I) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0x80, /* ...******... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 74 (J) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0x80, /* ...******... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x04, 0x00, /* .....*...... */ + 0x38, 0x00, /* ..***....... */ + 0x30, 0x00, /* ..**........ */ + + /* 75 (K) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xf0, 0xe0, /* ****....***. */ + 0x61, 0x80, /* .**....**... */ + 0x63, 0x00, /* .**...**.... */ + 0x66, 0x00, /* .**..**..... */ + 0x6c, 0x00, /* .**.**...... */ + 0x78, 0x00, /* .****....... */ + 0x78, 0x00, /* .****....... */ + 0x7c, 0x00, /* .*****...... */ + 0x6e, 0x00, /* .**.***..... */ + 0x67, 0x00, /* .**..***.... */ + 0x63, 0x80, /* .**...***... */ + 0x61, 0xc0, /* .**....***.. */ + 0x60, 0xe0, /* .**.....***. */ + 0xf0, 0x70, /* ****.....*** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 76 (L) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x78, 0x00, /* .****....... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x20, /* ..**......*. */ + 0x30, 0x20, /* ..**......*. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 77 (M) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xe0, 0x70, /* ***......*** */ + 0x60, 0xe0, /* .**.....***. */ + 0x70, 0xe0, /* .***....***. */ + 0x70, 0xe0, /* .***....***. */ + 0x70, 0xe0, /* .***....***. */ + 0x59, 0x60, /* .*.**..*.**. */ + 0x59, 0x60, /* .*.**..*.**. */ + 0x59, 0x60, /* .*.**..*.**. */ + 0x4d, 0x60, /* .*..**.*.**. */ + 0x4e, 0x60, /* .*..***..**. */ + 0x4e, 0x60, /* .*..***..**. */ + 0x44, 0x60, /* .*...*...**. */ + 0x44, 0x60, /* .*...*...**. */ + 0xe4, 0xf0, /* ***..*..**** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 78 (N) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xc0, 0x70, /* **.......*** */ + 0x60, 0x20, /* .**.......*. */ + 0x70, 0x20, /* .***......*. */ + 0x78, 0x20, /* .****.....*. */ + 0x58, 0x20, /* .*.**.....*. */ + 0x4c, 0x20, /* .*..**....*. */ + 0x46, 0x20, /* .*...**...*. */ + 0x47, 0x20, /* .*...***..*. */ + 0x43, 0x20, /* .*....**..*. */ + 0x41, 0xa0, /* .*.....**.*. */ + 0x40, 0xe0, /* .*......***. */ + 0x40, 0xe0, /* .*......***. */ + 0x40, 0x60, /* .*.......**. */ + 0xe0, 0x30, /* ***.......** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 79 (O) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x60, /* ..*......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x20, 0x40, /* ..*......*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 80 (P) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0x80, /* .********... */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0x60, /* ..**.....**. */ + 0x30, 0x60, /* ..**.....**. */ + 0x30, 0x60, /* ..**.....**. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x37, 0x80, /* ..**.****... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x78, 0x00, /* .****....... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 81 (Q) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x60, /* ..*......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x38, 0x40, /* ..***....*.. */ + 0x1f, 0x80, /* ...******... */ + 0x0e, 0x00, /* ....***..... */ + 0x1f, 0x00, /* ...*****.... */ + 0x23, 0x90, /* ..*...***..* */ + 0x01, 0xe0, /* .......****. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 82 (R) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xff, 0x00, /* ********.... */ + 0x61, 0x80, /* .**....**... */ + 0x60, 0xc0, /* .**.....**.. */ + 0x60, 0xc0, /* .**.....**.. */ + 0x60, 0xc0, /* .**.....**.. */ + 0x60, 0x80, /* .**.....*... */ + 0x7f, 0x00, /* .*******.... */ + 0x7c, 0x00, /* .*****...... */ + 0x6e, 0x00, /* .**.***..... */ + 0x67, 0x00, /* .**..***.... */ + 0x63, 0x80, /* .**...***... */ + 0x61, 0xc0, /* .**....***.. */ + 0x60, 0xe0, /* .**.....***. */ + 0xf0, 0x70, /* ****.....*** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 83 (S) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0xe0, /* ...********. */ + 0x30, 0x60, /* ..**.....**. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x70, 0x00, /* .***........ */ + 0x3c, 0x00, /* ..****...... */ + 0x1e, 0x00, /* ...****..... */ + 0x07, 0x80, /* .....****... */ + 0x01, 0xc0, /* .......***.. */ + 0x00, 0xe0, /* ........***. */ + 0x40, 0x60, /* .*.......**. */ + 0x40, 0x60, /* .*.......**. */ + 0x60, 0xc0, /* .**.....**.. */ + 0x7f, 0x80, /* .********... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 84 (T) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xe0, /* .**********. */ + 0x46, 0x20, /* .*...**...*. */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 85 (U) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xf0, 0x70, /* ****.....*** */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x70, 0x40, /* .***.....*.. */ + 0x3f, 0xc0, /* ..********.. */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 86 (V) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xe0, 0xe0, /* ***.....***. */ + 0x60, 0x40, /* .**......*.. */ + 0x30, 0x80, /* ..**....*... */ + 0x30, 0x80, /* ..**....*... */ + 0x30, 0x80, /* ..**....*... */ + 0x19, 0x00, /* ...**..*.... */ + 0x19, 0x00, /* ...**..*.... */ + 0x19, 0x00, /* ...**..*.... */ + 0x0c, 0x00, /* ....**...... */ + 0x0e, 0x00, /* ....***..... */ + 0x0e, 0x00, /* ....***..... */ + 0x04, 0x00, /* .....*...... */ + 0x04, 0x00, /* .....*...... */ + 0x04, 0x00, /* .....*...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 87 (W) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xfe, 0xf0, /* *******.**** */ + 0x66, 0x20, /* .**..**...*. */ + 0x66, 0x20, /* .**..**...*. */ + 0x66, 0x20, /* .**..**...*. */ + 0x76, 0x20, /* .***.**...*. */ + 0x77, 0x40, /* .***.***.*.. */ + 0x33, 0x40, /* ..**..**.*.. */ + 0x37, 0x40, /* ..**.***.*.. */ + 0x3b, 0xc0, /* ..***.****.. */ + 0x3b, 0x80, /* ..***.***... */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 88 (X) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xf0, 0x70, /* ****.....*** */ + 0x60, 0x20, /* .**.......*. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x38, 0x80, /* ..***...*... */ + 0x18, 0x80, /* ...**...*... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x11, 0x80, /* ...*...**... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x40, 0x60, /* .*.......**. */ + 0xe0, 0xf0, /* ***.....**** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 89 (Y) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xf0, 0x70, /* ****.....*** */ + 0x60, 0x20, /* .**.......*. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x18, 0x80, /* ...**...*... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 90 (Z) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x3f, 0xe0, /* ..*********. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x01, 0x80, /* .......**... */ + 0x01, 0x80, /* .......**... */ + 0x03, 0x00, /* ......**.... */ + 0x03, 0x00, /* ......**.... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x20, /* ...**.....*. */ + 0x3f, 0xe0, /* ..*********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 91 ([) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x07, 0xc0, /* .....*****.. */ + 0x07, 0xc0, /* .....*****.. */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x07, 0xc0, /* .....*****.. */ + 0x07, 0xc0, /* .....*****.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 92 (\) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x06, 0x00, /* .....**..... */ + 0x03, 0x00, /* ......**.... */ + 0x03, 0x00, /* ......**.... */ + 0x01, 0x80, /* .......**... */ + 0x01, 0x80, /* .......**... */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 93 (]) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7c, 0x00, /* .*****...... */ + 0x7c, 0x00, /* .*****...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x7c, 0x00, /* .*****...... */ + 0x7c, 0x00, /* .*****...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 94 (^) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x04, 0x00, /* .....*...... */ + 0x0e, 0x00, /* ....***..... */ + 0x1b, 0x00, /* ...**.**.... */ + 0x31, 0x80, /* ..**...**... */ + 0x60, 0xc0, /* .**.....**.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 95 (_) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xff, 0xe0, /* ***********. */ + 0xff, 0xe0, /* ***********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 96 (`) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x01, 0x00, /* .......*.... */ + 0x03, 0x00, /* ......**.... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x07, 0x80, /* .....****... */ + 0x07, 0x80, /* .....****... */ + 0x03, 0x00, /* ......**.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 97 (a) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x18, 0xc0, /* ...**...**.. */ + 0x10, 0xc0, /* ...*....**.. */ + 0x03, 0xc0, /* ......****.. */ + 0x1c, 0xc0, /* ...***..**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0xe0, /* ...****.***. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 98 (b) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x20, 0x00, /* ..*......... */ + 0x60, 0x00, /* .**......... */ + 0xe0, 0x00, /* ***......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x67, 0x80, /* .**..****... */ + 0x6f, 0xc0, /* .**.******.. */ + 0x70, 0xe0, /* .***....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0x60, /* .***.....**. */ + 0x78, 0xc0, /* .****...**.. */ + 0x4f, 0x80, /* .*..*****... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 99 (c) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0x80, /* ...******... */ + 0x31, 0xc0, /* ..**...***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x70, 0x40, /* .***.....*.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 100 (d) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x60, /* .........**. */ + 0x00, 0xe0, /* ........***. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x60, /* .........**. */ + 0x0f, 0x60, /* ....****.**. */ + 0x31, 0xe0, /* ..**...****. */ + 0x20, 0xe0, /* ..*.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0xe0, /* .***....***. */ + 0x39, 0x60, /* ..***..*.**. */ + 0x1e, 0x70, /* ...****..*** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 101 (e) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x30, 0xc0, /* ..**....**.. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x7f, 0xe0, /* .**********. */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x30, 0x00, /* ..**........ */ + 0x18, 0x60, /* ...**....**. */ + 0x0f, 0x80, /* ....*****... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 102 (f) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x03, 0x80, /* ......***... */ + 0x04, 0xc0, /* .....*..**.. */ + 0x04, 0xc0, /* .....*..**.. */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x1f, 0x80, /* ...******... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x1e, 0x00, /* ...****..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 103 (g) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0x20, /* ...*****..*. */ + 0x31, 0xe0, /* ..**...****. */ + 0x60, 0xc0, /* .**.....**.. */ + 0x60, 0xc0, /* .**.....**.. */ + 0x60, 0xc0, /* .**.....**.. */ + 0x31, 0x80, /* ..**...**... */ + 0x3f, 0x00, /* ..******.... */ + 0x60, 0x00, /* .**......... */ + 0x7f, 0xc0, /* .*********.. */ + 0x3f, 0xe0, /* ..*********. */ + 0x20, 0x60, /* ..*......**. */ + 0x40, 0x20, /* .*........*. */ + 0x40, 0x20, /* .*........*. */ + 0x7f, 0xc0, /* .*********.. */ + 0x3f, 0x80, /* ..*******... */ + + /* 104 (h) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x10, 0x00, /* ...*........ */ + 0x30, 0x00, /* ..**........ */ + 0x70, 0x00, /* .***........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x37, 0x80, /* ..**.****... */ + 0x39, 0xc0, /* ..***..***.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x79, 0xe0, /* .****..****. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 105 (i) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1e, 0x00, /* ...****..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 106 (j) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x03, 0xc0, /* ......****.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x38, 0x80, /* ..***...*... */ + 0x1f, 0x00, /* ...*****.... */ + 0x0e, 0x00, /* ....***..... */ + + /* 107 (k) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x60, 0x00, /* .**......... */ + 0xe0, 0x00, /* ***......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x61, 0xc0, /* .**....***.. */ + 0x63, 0x00, /* .**...**.... */ + 0x66, 0x00, /* .**..**..... */ + 0x7c, 0x00, /* .*****...... */ + 0x78, 0x00, /* .****....... */ + 0x7c, 0x00, /* .*****...... */ + 0x6e, 0x00, /* .**.***..... */ + 0x67, 0x00, /* .**..***.... */ + 0x63, 0x80, /* .**...***... */ + 0xf1, 0xe0, /* ****...****. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 108 (l) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1e, 0x00, /* ...****..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 109 (m) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xdd, 0xc0, /* **.***.***.. */ + 0x6e, 0xe0, /* .**.***.***. */ + 0x66, 0x60, /* .**..**..**. */ + 0x66, 0x60, /* .**..**..**. */ + 0x66, 0x60, /* .**..**..**. */ + 0x66, 0x60, /* .**..**..**. */ + 0x66, 0x60, /* .**..**..**. */ + 0x66, 0x60, /* .**..**..**. */ + 0x66, 0x60, /* .**..**..**. */ + 0xef, 0x70, /* ***.****.*** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 110 (n) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x27, 0x80, /* ..*..****... */ + 0x79, 0xc0, /* .****..***.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x79, 0xe0, /* .****..****. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 111 (o) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xe0, /* ..*.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0x40, /* .***.....*.. */ + 0x38, 0x80, /* ..***...*... */ + 0x1f, 0x00, /* ...*****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 112 (p) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xef, 0x80, /* ***.*****... */ + 0x71, 0xc0, /* .***...***.. */ + 0x60, 0xe0, /* .**.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x40, /* .**......*.. */ + 0x70, 0x80, /* .***....*... */ + 0x7f, 0x00, /* .*******.... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0xf0, 0x00, /* ****........ */ + + /* 113 (q) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x20, /* ....****..*. */ + 0x11, 0xe0, /* ...*...****. */ + 0x20, 0xe0, /* ..*.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0x60, /* .***.....**. */ + 0x38, 0xe0, /* ..***...***. */ + 0x1f, 0xe0, /* ...********. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0xf0, /* ........**** */ + + /* 114 (r) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x73, 0x80, /* .***..***... */ + 0x34, 0xc0, /* ..**.*..**.. */ + 0x38, 0xc0, /* ..***...**.. */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x78, 0x00, /* .****....... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 115 (s) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0xc0, /* ...*******.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x38, 0x00, /* ..***....... */ + 0x1e, 0x00, /* ...****..... */ + 0x07, 0x80, /* .....****... */ + 0x01, 0xc0, /* .......***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x3f, 0x80, /* ..*******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 116 (t) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x04, 0x00, /* .....*...... */ + 0x04, 0x00, /* .....*...... */ + 0x0c, 0x00, /* ....**...... */ + 0x7f, 0xc0, /* .*********.. */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x20, /* ....**....*. */ + 0x0e, 0x40, /* ....***..*.. */ + 0x07, 0x80, /* .....****... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 117 (u) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x79, 0xe0, /* .****..****. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0x60, /* ...****..**. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 118 (v) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xf0, 0x70, /* ****.....*** */ + 0x60, 0x20, /* .**.......*. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x18, 0x80, /* ...**...*... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 119 (w) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xff, 0x70, /* ********.*** */ + 0x66, 0x20, /* .**..**...*. */ + 0x66, 0x20, /* .**..**...*. */ + 0x66, 0x20, /* .**..**...*. */ + 0x37, 0x40, /* ..**.***.*.. */ + 0x3b, 0x40, /* ..***.**.*.. */ + 0x3b, 0x40, /* ..***.**.*.. */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 120 (x) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xf8, 0xf0, /* *****...**** */ + 0x70, 0x40, /* .***.....*.. */ + 0x38, 0x80, /* ..***...*... */ + 0x1d, 0x00, /* ...***.*.... */ + 0x0e, 0x00, /* ....***..... */ + 0x07, 0x00, /* .....***.... */ + 0x0b, 0x80, /* ....*.***... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xe0, /* ..*.....***. */ + 0xf1, 0xf0, /* ****...***** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 121 (y) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xf0, 0xf0, /* ****....**** */ + 0x60, 0x20, /* .**.......*. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x18, 0x80, /* ...**...*... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x04, 0x00, /* .....*...... */ + 0x0c, 0x00, /* ....**...... */ + 0x08, 0x00, /* ....*....... */ + 0x78, 0x00, /* .****....... */ + 0x70, 0x00, /* .***........ */ + + /* 122 (z) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xe0, /* .**********. */ + 0x60, 0xe0, /* .**.....***. */ + 0x41, 0xc0, /* .*.....***.. */ + 0x03, 0x80, /* ......***... */ + 0x07, 0x00, /* .....***.... */ + 0x0e, 0x00, /* ....***..... */ + 0x1c, 0x00, /* ...***...... */ + 0x38, 0x20, /* ..***.....*. */ + 0x70, 0x60, /* .***.....**. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 123 ({) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x01, 0xc0, /* .......***.. */ + 0x03, 0x00, /* ......**.... */ + 0x03, 0x00, /* ......**.... */ + 0x01, 0x80, /* .......**... */ + 0x01, 0x80, /* .......**... */ + 0x01, 0x80, /* .......**... */ + 0x03, 0x00, /* ......**.... */ + 0x07, 0x00, /* .....***.... */ + 0x03, 0x00, /* ......**.... */ + 0x01, 0x80, /* .......**... */ + 0x01, 0x80, /* .......**... */ + 0x01, 0x80, /* .......**... */ + 0x03, 0x00, /* ......**.... */ + 0x03, 0x00, /* ......**.... */ + 0x01, 0xc0, /* .......***.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 124 (|) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + + /* 125 (}) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x38, 0x00, /* ..***....... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x0c, 0x00, /* ....**...... */ + 0x0e, 0x00, /* ....***..... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x0c, 0x00, /* ....**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x38, 0x00, /* ..***....... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 126 (~) */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1c, 0x20, /* ...***....*. */ + 0x3e, 0x60, /* ..*****..**. */ + 0x36, 0xc0, /* ..**.**.**.. */ + 0x67, 0xc0, /* .**..*****.. */ + 0x43, 0x80, /* .*....***... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 127 */ + 0xaa, 0xa0, /* *.*.*.*.*.*. */ + 0x55, 0x50, /* .*.*.*.*.*.* */ + 0xaa, 0xa0, /* *.*.*.*.*.*. */ + 0x55, 0x50, /* .*.*.*.*.*.* */ + 0xaa, 0xa0, /* *.*.*.*.*.*. */ + 0x55, 0x50, /* .*.*.*.*.*.* */ + 0xaa, 0xa0, /* *.*.*.*.*.*. */ + 0x55, 0x50, /* .*.*.*.*.*.* */ + 0xaa, 0xa0, /* *.*.*.*.*.*. */ + 0x55, 0x50, /* .*.*.*.*.*.* */ + 0xaa, 0xa0, /* *.*.*.*.*.*. */ + 0x55, 0x50, /* .*.*.*.*.*.* */ + 0xaa, 0xa0, /* *.*.*.*.*.*. */ + 0x55, 0x50, /* .*.*.*.*.*.* */ + 0xaa, 0xa0, /* *.*.*.*.*.*. */ + 0x55, 0x50, /* .*.*.*.*.*.* */ + 0xaa, 0xa0, /* *.*.*.*.*.*. */ + 0x55, 0x50, /* .*.*.*.*.*.* */ + 0xaa, 0xa0, /* *.*.*.*.*.*. */ + 0x55, 0x50, /* .*.*.*.*.*.* */ + 0xaa, 0xa0, /* *.*.*.*.*.*. */ + 0x55, 0x50, /* .*.*.*.*.*.* */ + + /* 128 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 129 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 130 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 131 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 132 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 133 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 134 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 135 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 136 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 137 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 138 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 139 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 140 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 141 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 142 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 143 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 144 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 145 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 146 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 147 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 148 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 149 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 150 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 151 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 152 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 153 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 154 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 155 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 156 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 157 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 158 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 159 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 160 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 161 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 162 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x01, 0x00, /* .......*.... */ + 0x01, 0x00, /* .......*.... */ + 0x03, 0x00, /* ......**.... */ + 0x02, 0x00, /* ......*..... */ + 0x1f, 0x00, /* ...*****.... */ + 0x37, 0x80, /* ..**.****... */ + 0x25, 0x80, /* ..*..*.**... */ + 0x64, 0x00, /* .**..*...... */ + 0x6c, 0x00, /* .**.**...... */ + 0x68, 0x00, /* .**.*....... */ + 0x78, 0x80, /* .****...*... */ + 0x39, 0x80, /* ..***..**... */ + 0x1f, 0x00, /* ...*****.... */ + 0x10, 0x00, /* ...*........ */ + 0x30, 0x00, /* ..**........ */ + 0x20, 0x00, /* ..*......... */ + 0x20, 0x00, /* ..*......... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 163 */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x10, 0x00, /* ...*........ */ + 0x10, 0x00, /* ...*........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x3e, 0x00, /* ..*****..... */ + 0x7c, 0x00, /* .*****...... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x00, /* ...**....... */ + 0x3f, 0x20, /* ..******..*. */ + 0x3f, 0xe0, /* ..*********. */ + 0x31, 0xc0, /* ..**...***.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 164 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x60, 0x20, /* .**.......*. */ + 0x77, 0x40, /* .***.***.*.. */ + 0x3b, 0x80, /* ..***.***... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x38, 0x80, /* ..***...*... */ + 0x1d, 0xc0, /* ...***.***.. */ + 0x2e, 0xe0, /* ..*.***.***. */ + 0x40, 0x60, /* .*.......**. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 165 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xf0, 0x70, /* ****.....*** */ + 0x60, 0x20, /* .**.......*. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x18, 0x80, /* ...**...*... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x06, 0x00, /* .....**..... */ + 0x3f, 0xc0, /* ..********.. */ + 0x06, 0x00, /* .....**..... */ + 0x3f, 0xc0, /* ..********.. */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 166 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + + /* 167 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0xe0, /* ....*******. */ + 0x18, 0x60, /* ...**....**. */ + 0x30, 0x20, /* ..**......*. */ + 0x38, 0x20, /* ..***.....*. */ + 0x1e, 0x00, /* ...****..... */ + 0x1f, 0x80, /* ...******... */ + 0x31, 0xc0, /* ..**...***.. */ + 0x60, 0xe0, /* .**.....***. */ + 0x70, 0x60, /* .***.....**. */ + 0x38, 0xc0, /* ..***...**.. */ + 0x1f, 0x80, /* ...******... */ + 0x07, 0x80, /* .....****... */ + 0x41, 0xc0, /* .*.....***.. */ + 0x40, 0xc0, /* .*......**.. */ + 0x61, 0x80, /* .**....**... */ + 0x7f, 0x00, /* .*******.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 168 */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 169 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x10, 0x80, /* ...*....*... */ + 0x20, 0x40, /* ..*......*.. */ + 0x2f, 0x40, /* ..*.****.*.. */ + 0x59, 0xa0, /* .*.**..**.*. */ + 0x59, 0xa0, /* .*.**..**.*. */ + 0x58, 0x20, /* .*.**.....*. */ + 0x58, 0x20, /* .*.**.....*. */ + 0x59, 0xa0, /* .*.**..**.*. */ + 0x59, 0xa0, /* .*.**..**.*. */ + 0x2f, 0x40, /* ..*.****.*.. */ + 0x20, 0x40, /* ..*......*.. */ + 0x10, 0x80, /* ...*....*... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 170 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0e, 0x00, /* ....***..... */ + 0x1f, 0x00, /* ...*****.... */ + 0x13, 0x80, /* ...*..***... */ + 0x0f, 0x80, /* ....*****... */ + 0x19, 0x80, /* ...**..**... */ + 0x31, 0x80, /* ..**...**... */ + 0x3f, 0xc0, /* ..********.. */ + 0x1e, 0xc0, /* ...****.**.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x3f, 0xe0, /* ..*********. */ + 0x7f, 0xc0, /* .*********.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 171 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x02, 0x20, /* ......*...*. */ + 0x04, 0x40, /* .....*...*.. */ + 0x08, 0x80, /* ....*...*... */ + 0x11, 0x00, /* ...*...*.... */ + 0x33, 0x00, /* ..**..**.... */ + 0x19, 0x80, /* ...**..**... */ + 0x0c, 0xc0, /* ....**..**.. */ + 0x06, 0x60, /* .....**..**. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 172 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x60, /* .........**. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 173 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0x80, /* ...******... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 174 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x10, 0x80, /* ...*....*... */ + 0x20, 0x40, /* ..*......*.. */ + 0x3f, 0x40, /* ..******.*.. */ + 0x59, 0xa0, /* .*.**..**.*. */ + 0x59, 0xa0, /* .*.**..**.*. */ + 0x5f, 0xa0, /* .*.******.*. */ + 0x5b, 0x20, /* .*.**.**..*. */ + 0x5b, 0x20, /* .*.**.**..*. */ + 0x59, 0xa0, /* .*.**..**.*. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x20, 0x40, /* ..*......*.. */ + 0x10, 0x80, /* ...*....*... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 175 */ + 0x3f, 0xc0, /* ..********.. */ + 0x3f, 0xc0, /* ..********.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 176 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0e, 0x00, /* ....***..... */ + 0x17, 0x00, /* ...*.***.... */ + 0x23, 0x80, /* ..*...***... */ + 0x61, 0x80, /* .**....**... */ + 0x61, 0x80, /* .**....**... */ + 0x71, 0x00, /* .***...*.... */ + 0x3a, 0x00, /* ..***.*..... */ + 0x1c, 0x00, /* ...***...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 177 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 178 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0e, 0x00, /* ....***..... */ + 0x1f, 0x00, /* ...*****.... */ + 0x13, 0x00, /* ...*..**.... */ + 0x03, 0x00, /* ......**.... */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x00, /* ...**....... */ + 0x1f, 0x00, /* ...*****.... */ + 0x1f, 0x00, /* ...*****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 179 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0e, 0x00, /* ....***..... */ + 0x1f, 0x00, /* ...*****.... */ + 0x13, 0x00, /* ...*..**.... */ + 0x03, 0x00, /* ......**.... */ + 0x06, 0x00, /* .....**..... */ + 0x03, 0x00, /* ......**.... */ + 0x13, 0x00, /* ...*..**.... */ + 0x1f, 0x00, /* ...*****.... */ + 0x0e, 0x00, /* ....***..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 180 */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 181 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x79, 0xe0, /* .****..****. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x3e, 0x60, /* ..*****..**. */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x60, 0x00, /* .**......... */ + + /* 182 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0xc0, /* ...*******.. */ + 0x3e, 0xc0, /* ..*****.**.. */ + 0x7e, 0xc0, /* .******.**.. */ + 0x7e, 0xc0, /* .******.**.. */ + 0x7e, 0xc0, /* .******.**.. */ + 0x3e, 0xc0, /* ..*****.**.. */ + 0x1e, 0xc0, /* ...****.**.. */ + 0x06, 0xc0, /* .....**.**.. */ + 0x06, 0xc0, /* .....**.**.. */ + 0x06, 0xc0, /* .....**.**.. */ + 0x06, 0xc0, /* .....**.**.. */ + 0x06, 0xc0, /* .....**.**.. */ + 0x06, 0xc0, /* .....**.**.. */ + 0x06, 0xc0, /* .....**.**.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 183 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x0f, 0x00, /* ....****.... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 184 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x02, 0x00, /* ......*..... */ + 0x03, 0x00, /* ......**.... */ + 0x01, 0x80, /* .......**... */ + 0x09, 0x80, /* ....*..**... */ + 0x07, 0x00, /* .....***.... */ + + /* 185 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x0e, 0x00, /* ....***..... */ + 0x0e, 0x00, /* ....***..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 186 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x07, 0x00, /* .....***.... */ + 0x0b, 0x80, /* ....*.***... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x38, 0x80, /* ..***...*... */ + 0x1d, 0x00, /* ...***.*.... */ + 0x0e, 0x00, /* ....***..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x3f, 0xe0, /* ..*********. */ + 0x7f, 0xc0, /* .*********.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 187 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x66, 0x00, /* .**..**..... */ + 0x33, 0x00, /* ..**..**.... */ + 0x19, 0x80, /* ...**..**... */ + 0x0c, 0xc0, /* ....**..**.. */ + 0x08, 0x80, /* ....*...*... */ + 0x11, 0x00, /* ...*...*.... */ + 0x22, 0x00, /* ..*...*..... */ + 0x44, 0x00, /* .*...*...... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 188 */ + 0x00, 0x00, /* ............ */ + 0x18, 0x00, /* ...**....... */ + 0x38, 0x00, /* ..***....... */ + 0x38, 0x00, /* ..***....... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x20, /* ...**.....*. */ + 0x18, 0x60, /* ...**....**. */ + 0x18, 0xc0, /* ...**...**.. */ + 0x19, 0x80, /* ...**..**... */ + 0x3f, 0x40, /* ..******.*.. */ + 0x06, 0xc0, /* .....**.**.. */ + 0x0d, 0xc0, /* ....**.***.. */ + 0x19, 0xc0, /* ...**..***.. */ + 0x32, 0xc0, /* ..**..*.**.. */ + 0x64, 0xc0, /* .**..*..**.. */ + 0x47, 0xe0, /* .*...******. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 189 */ + 0x00, 0x00, /* ............ */ + 0x18, 0x00, /* ...**....... */ + 0x38, 0x00, /* ..***....... */ + 0x38, 0x00, /* ..***....... */ + 0x18, 0x00, /* ...**....... */ + 0x18, 0x20, /* ...**.....*. */ + 0x18, 0x60, /* ...**....**. */ + 0x18, 0xc0, /* ...**...**.. */ + 0x19, 0x80, /* ...**..**... */ + 0x3f, 0xc0, /* ..********.. */ + 0x07, 0xe0, /* .....******. */ + 0x0f, 0x60, /* ....****.**. */ + 0x1a, 0x60, /* ...**.*..**. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x61, 0x80, /* .**....**... */ + 0x43, 0x00, /* .*....**.... */ + 0x03, 0xe0, /* ......*****. */ + 0x03, 0xe0, /* ......*****. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 190 */ + 0x00, 0x00, /* ............ */ + 0x38, 0x00, /* ..***....... */ + 0x7c, 0x00, /* .*****...... */ + 0x4c, 0x00, /* .*..**...... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x20, /* ...**.....*. */ + 0x0c, 0x60, /* ....**...**. */ + 0x4c, 0xc0, /* .*..**..**.. */ + 0x7d, 0x80, /* .*****.**... */ + 0x3b, 0x40, /* ..***.**.*.. */ + 0x06, 0xc0, /* .....**.**.. */ + 0x0d, 0xc0, /* ....**.***.. */ + 0x19, 0xc0, /* ...**..***.. */ + 0x32, 0xc0, /* ..**..*.**.. */ + 0x64, 0xc0, /* .**..*..**.. */ + 0x47, 0xe0, /* .*...******. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0xc0, /* ........**.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 191 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x03, 0x00, /* ......**.... */ + 0x03, 0x00, /* ......**.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x03, 0x00, /* ......**.... */ + 0x03, 0x00, /* ......**.... */ + 0x06, 0x00, /* .....**..... */ + 0x0c, 0x00, /* ....**...... */ + 0x18, 0x00, /* ...**....... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x40, /* ..**.....*.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1f, 0x80, /* ...******... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 192 */ + 0x1c, 0x00, /* ...***...... */ + 0x0f, 0x00, /* ....****.... */ + 0x03, 0x80, /* ......***... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x09, 0x00, /* ....*..*.... */ + 0x11, 0x80, /* ...*...**... */ + 0x11, 0x80, /* ...*...**... */ + 0x10, 0x80, /* ...*....*... */ + 0x3f, 0xc0, /* ..********.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x40, /* ..*......*.. */ + 0x40, 0x60, /* .*.......**. */ + 0x40, 0x60, /* .*.......**. */ + 0xe0, 0xf0, /* ***.....**** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 193 */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x09, 0x00, /* ....*..*.... */ + 0x11, 0x80, /* ...*...**... */ + 0x11, 0x80, /* ...*...**... */ + 0x10, 0x80, /* ...*....*... */ + 0x3f, 0xc0, /* ..********.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x40, /* ..*......*.. */ + 0x40, 0x60, /* .*.......**. */ + 0x40, 0x60, /* .*.......**. */ + 0xe0, 0xf0, /* ***.....**** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 194 */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x09, 0x00, /* ....*..*.... */ + 0x11, 0x80, /* ...*...**... */ + 0x11, 0x80, /* ...*...**... */ + 0x10, 0x80, /* ...*....*... */ + 0x3f, 0xc0, /* ..********.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x40, /* ..*......*.. */ + 0x40, 0x60, /* .*.......**. */ + 0x40, 0x60, /* .*.......**. */ + 0xe0, 0xf0, /* ***.....**** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 195 */ + 0x0c, 0xc0, /* ....**..**.. */ + 0x1f, 0x80, /* ...******... */ + 0x33, 0x00, /* ..**..**.... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x09, 0x00, /* ....*..*.... */ + 0x11, 0x80, /* ...*...**... */ + 0x11, 0x80, /* ...*...**... */ + 0x10, 0x80, /* ...*....*... */ + 0x3f, 0xc0, /* ..********.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x40, /* ..*......*.. */ + 0x40, 0x60, /* .*.......**. */ + 0x40, 0x60, /* .*.......**. */ + 0xe0, 0xf0, /* ***.....**** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 196 */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x09, 0x00, /* ....*..*.... */ + 0x11, 0x80, /* ...*...**... */ + 0x11, 0x80, /* ...*...**... */ + 0x10, 0x80, /* ...*....*... */ + 0x3f, 0xc0, /* ..********.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x40, /* ..*......*.. */ + 0x40, 0x60, /* .*.......**. */ + 0x40, 0x60, /* .*.......**. */ + 0xe0, 0xf0, /* ***.....**** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 197 */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x0f, 0x00, /* ....****.... */ + 0x06, 0x00, /* .....**..... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x0b, 0x00, /* ....*.**.... */ + 0x09, 0x00, /* ....*..*.... */ + 0x11, 0x80, /* ...*...**... */ + 0x11, 0x80, /* ...*...**... */ + 0x10, 0x80, /* ...*....*... */ + 0x3f, 0xc0, /* ..********.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x40, /* ..*......*.. */ + 0x40, 0x60, /* .*.......**. */ + 0x40, 0x60, /* .*.......**. */ + 0xe0, 0xf0, /* ***.....**** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 198 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0xe0, /* ....*******. */ + 0x0e, 0x20, /* ....***...*. */ + 0x16, 0x20, /* ...*.**...*. */ + 0x16, 0x00, /* ...*.**..... */ + 0x16, 0x00, /* ...*.**..... */ + 0x16, 0x40, /* ...*.**..*.. */ + 0x27, 0xc0, /* ..*..*****.. */ + 0x26, 0x40, /* ..*..**..*.. */ + 0x3e, 0x00, /* ..*****..... */ + 0x26, 0x00, /* ..*..**..... */ + 0x46, 0x00, /* .*...**..... */ + 0x46, 0x10, /* .*...**....* */ + 0x46, 0x10, /* .*...**....* */ + 0xe7, 0xf0, /* ***..******* */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 199 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0xc0, /* ....******.. */ + 0x10, 0x60, /* ...*.....**. */ + 0x20, 0x20, /* ..*.......*. */ + 0x20, 0x00, /* ..*......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x20, 0x00, /* ..*......... */ + 0x30, 0x20, /* ..**......*. */ + 0x18, 0x40, /* ...**....*.. */ + 0x0f, 0x80, /* ....*****... */ + 0x02, 0x00, /* ......*..... */ + 0x03, 0x00, /* ......**.... */ + 0x01, 0x80, /* .......**... */ + 0x09, 0x80, /* ....*..**... */ + 0x07, 0x00, /* .....***.... */ + + /* 200 */ + 0x1c, 0x00, /* ...***...... */ + 0x0f, 0x00, /* ....****.... */ + 0x03, 0x80, /* ......***... */ + 0x7f, 0xc0, /* .*********.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x80, /* ..**....*... */ + 0x3f, 0x80, /* ..*******... */ + 0x30, 0x80, /* ..**....*... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x20, /* ..**......*. */ + 0x30, 0x20, /* ..**......*. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 201 */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0x7f, 0xc0, /* .*********.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x80, /* ..**....*... */ + 0x3f, 0x80, /* ..*******... */ + 0x30, 0x80, /* ..**....*... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x20, /* ..**......*. */ + 0x30, 0x20, /* ..**......*. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 202 */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x7f, 0xc0, /* .*********.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x80, /* ..**....*... */ + 0x3f, 0x80, /* ..*******... */ + 0x30, 0x80, /* ..**....*... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x20, /* ..**......*. */ + 0x30, 0x20, /* ..**......*. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 203 */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xc0, /* .*********.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x80, /* ..**....*... */ + 0x3f, 0x80, /* ..*******... */ + 0x30, 0x80, /* ..**....*... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x20, /* ..**......*. */ + 0x30, 0x20, /* ..**......*. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 204 */ + 0x1c, 0x00, /* ...***...... */ + 0x0f, 0x00, /* ....****.... */ + 0x03, 0x80, /* ......***... */ + 0x1f, 0x80, /* ...******... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 205 */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0x1f, 0x80, /* ...******... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 206 */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x1f, 0x80, /* ...******... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 207 */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x1f, 0x80, /* ...******... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 208 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xff, 0x00, /* ********.... */ + 0x61, 0xc0, /* .**....***.. */ + 0x60, 0xc0, /* .**.....**.. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0xf8, 0x60, /* *****....**. */ + 0xf8, 0x60, /* *****....**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x40, /* .**......*.. */ + 0x61, 0x80, /* .**....**... */ + 0xfe, 0x00, /* *******..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 209 */ + 0x0c, 0xc0, /* ....**..**.. */ + 0x1f, 0x80, /* ...******... */ + 0x33, 0x00, /* ..**..**.... */ + 0xc0, 0x70, /* **.......*** */ + 0x60, 0x20, /* .**.......*. */ + 0x70, 0x20, /* .***......*. */ + 0x78, 0x20, /* .****.....*. */ + 0x58, 0x20, /* .*.**.....*. */ + 0x4c, 0x20, /* .*..**....*. */ + 0x46, 0x20, /* .*...**...*. */ + 0x47, 0x20, /* .*...***..*. */ + 0x43, 0x20, /* .*....**..*. */ + 0x41, 0xa0, /* .*.....**.*. */ + 0x40, 0xe0, /* .*......***. */ + 0x40, 0xe0, /* .*......***. */ + 0x40, 0x60, /* .*.......**. */ + 0xe0, 0x30, /* ***.......** */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 210 */ + 0x1c, 0x00, /* ...***...... */ + 0x0f, 0x00, /* ....****.... */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x60, /* ..*......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x20, 0x40, /* ..*......*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 211 */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0x0f, 0x00, /* ....****.... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x60, /* ..*......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x20, 0x40, /* ..*......*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 212 */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x0f, 0x00, /* ....****.... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x60, /* ..*......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x20, 0x40, /* ..*......*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 213 */ + 0x0c, 0xc0, /* ....**..**.. */ + 0x1f, 0x80, /* ...******... */ + 0x33, 0x00, /* ..**..**.... */ + 0x0f, 0x00, /* ....****.... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x60, /* ..*......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x20, 0x40, /* ..*......*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 214 */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x20, 0x60, /* ..*......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x20, 0x40, /* ..*......*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 215 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x60, 0x60, /* .**......**. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x19, 0x80, /* ...**..**... */ + 0x0f, 0x00, /* ....****.... */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x30, 0xc0, /* ..**....**.. */ + 0x60, 0x60, /* .**......**. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 216 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x60, /* .........**. */ + 0x0f, 0xc0, /* ....******.. */ + 0x11, 0xc0, /* ...*...***.. */ + 0x21, 0xc0, /* ..*....***.. */ + 0x21, 0xe0, /* ..*....****. */ + 0x63, 0x60, /* .**...**.**. */ + 0x63, 0x60, /* .**...**.**. */ + 0x66, 0x60, /* .**..**..**. */ + 0x6c, 0x60, /* .**.**...**. */ + 0x6c, 0x60, /* .**.**...**. */ + 0x78, 0x60, /* .****....**. */ + 0x38, 0x40, /* ..***....*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x38, 0x80, /* ..***...*... */ + 0x6f, 0x00, /* .**.****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 217 */ + 0x1c, 0x00, /* ...***...... */ + 0x0f, 0x00, /* ....****.... */ + 0x03, 0x80, /* ......***... */ + 0xf0, 0x70, /* ****.....*** */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x70, 0x40, /* .***.....*.. */ + 0x3f, 0xc0, /* ..********.. */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 218 */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0xf0, 0x70, /* ****.....*** */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x70, 0x40, /* .***.....*.. */ + 0x3f, 0xc0, /* ..********.. */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 219 */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0xf0, 0x70, /* ****.....*** */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x70, 0x40, /* .***.....*.. */ + 0x3f, 0xc0, /* ..********.. */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 220 */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0xf0, 0x70, /* ****.....*** */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x60, 0x20, /* .**.......*. */ + 0x70, 0x40, /* .***.....*.. */ + 0x3f, 0xc0, /* ..********.. */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 221 */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0xf0, 0x70, /* ****.....*** */ + 0x60, 0x20, /* .**.......*. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x18, 0x80, /* ...**...*... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 222 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x78, 0x00, /* .****....... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x3f, 0x80, /* ..*******... */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0x60, /* ..**.....**. */ + 0x30, 0x60, /* ..**.....**. */ + 0x30, 0x60, /* ..**.....**. */ + 0x30, 0x60, /* ..**.....**. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x3f, 0x80, /* ..*******... */ + 0x30, 0x00, /* ..**........ */ + 0x30, 0x00, /* ..**........ */ + 0x78, 0x00, /* .****....... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 223 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x31, 0x80, /* ..**...**... */ + 0x31, 0x80, /* ..**...**... */ + 0x33, 0x80, /* ..**..***... */ + 0x36, 0x00, /* ..**.**..... */ + 0x36, 0x00, /* ..**.**..... */ + 0x36, 0x00, /* ..**.**..... */ + 0x33, 0x80, /* ..**..***... */ + 0x31, 0xc0, /* ..**...***.. */ + 0x30, 0xe0, /* ..**....***. */ + 0x34, 0x60, /* ..**.*...**. */ + 0x36, 0x60, /* ..**.**..**. */ + 0x77, 0xc0, /* .***.*****.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 224 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1c, 0x00, /* ...***...... */ + 0x0f, 0x00, /* ....****.... */ + 0x03, 0x80, /* ......***... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x18, 0xc0, /* ...**...**.. */ + 0x10, 0xc0, /* ...*....**.. */ + 0x03, 0xc0, /* ......****.. */ + 0x1c, 0xc0, /* ...***..**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0xe0, /* ...****.***. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 225 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x18, 0xc0, /* ...**...**.. */ + 0x10, 0xc0, /* ...*....**.. */ + 0x03, 0xc0, /* ......****.. */ + 0x1c, 0xc0, /* ...***..**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0xe0, /* ...****.***. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 226 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x18, 0xc0, /* ...**...**.. */ + 0x10, 0xc0, /* ...*....**.. */ + 0x03, 0xc0, /* ......****.. */ + 0x1c, 0xc0, /* ...***..**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0xe0, /* ...****.***. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 227 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0c, 0xc0, /* ....**..**.. */ + 0x1f, 0x80, /* ...******... */ + 0x33, 0x00, /* ..**..**.... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x18, 0xc0, /* ...**...**.. */ + 0x10, 0xc0, /* ...*....**.. */ + 0x03, 0xc0, /* ......****.. */ + 0x1c, 0xc0, /* ...***..**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0xe0, /* ...****.***. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 228 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x18, 0xc0, /* ...**...**.. */ + 0x10, 0xc0, /* ...*....**.. */ + 0x03, 0xc0, /* ......****.. */ + 0x1c, 0xc0, /* ...***..**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0xe0, /* ...****.***. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 229 */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x0f, 0x00, /* ....****.... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x18, 0xc0, /* ...**...**.. */ + 0x10, 0xc0, /* ...*....**.. */ + 0x03, 0xc0, /* ......****.. */ + 0x1c, 0xc0, /* ...***..**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0xe0, /* ...****.***. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 230 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0x80, /* ...******... */ + 0x36, 0x40, /* ..**.**..*.. */ + 0x26, 0x60, /* ..*..**..**. */ + 0x0e, 0x60, /* ....***..**. */ + 0x3f, 0xe0, /* ..*********. */ + 0x66, 0x00, /* .**..**..... */ + 0x66, 0x00, /* .**..**..... */ + 0x66, 0x00, /* .**..**..... */ + 0x67, 0x60, /* .**..***.**. */ + 0x3f, 0xc0, /* ..********.. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 231 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1f, 0x80, /* ...******... */ + 0x31, 0xc0, /* ..**...***.. */ + 0x20, 0xc0, /* ..*.....**.. */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x70, 0x40, /* .***.....*.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x1f, 0x80, /* ...******... */ + 0x02, 0x00, /* ......*..... */ + 0x03, 0x00, /* ......**.... */ + 0x01, 0x80, /* .......**... */ + 0x09, 0x80, /* ....*..**... */ + 0x07, 0x00, /* .....***.... */ + + /* 232 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1c, 0x00, /* ...***...... */ + 0x0f, 0x00, /* ....****.... */ + 0x03, 0x80, /* ......***... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x30, 0xc0, /* ..**....**.. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x7f, 0xe0, /* .**********. */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x30, 0x00, /* ..**........ */ + 0x18, 0x60, /* ...**....**. */ + 0x0f, 0x80, /* ....*****... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 233 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x30, 0xc0, /* ..**....**.. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x7f, 0xe0, /* .**********. */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x30, 0x00, /* ..**........ */ + 0x18, 0x60, /* ...**....**. */ + 0x0f, 0x80, /* ....*****... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 234 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x30, 0xc0, /* ..**....**.. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x7f, 0xe0, /* .**********. */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x30, 0x00, /* ..**........ */ + 0x18, 0x60, /* ...**....**. */ + 0x0f, 0x80, /* ....*****... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 235 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x00, /* ....****.... */ + 0x30, 0xc0, /* ..**....**.. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x7f, 0xe0, /* .**********. */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x30, 0x00, /* ..**........ */ + 0x18, 0x60, /* ...**....**. */ + 0x0f, 0x80, /* ....*****... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 236 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1c, 0x00, /* ...***...... */ + 0x0f, 0x00, /* ....****.... */ + 0x03, 0x80, /* ......***... */ + 0x00, 0x00, /* ............ */ + 0x1e, 0x00, /* ...****..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 237 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0x00, 0x00, /* ............ */ + 0x1e, 0x00, /* ...****..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 238 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x1e, 0x00, /* ...****..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 239 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1e, 0x00, /* ...****..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x80, /* ...******... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 240 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x30, 0xc0, /* ..**....**.. */ + 0x1f, 0x80, /* ...******... */ + 0x06, 0x00, /* .....**..... */ + 0x1f, 0x00, /* ...*****.... */ + 0x31, 0x80, /* ..**...**... */ + 0x01, 0xc0, /* .......***.. */ + 0x0f, 0xc0, /* ....******.. */ + 0x10, 0xe0, /* ...*....***. */ + 0x20, 0xe0, /* ..*.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0x40, /* .***.....*.. */ + 0x38, 0x80, /* ..***...*... */ + 0x1f, 0x00, /* ...*****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 241 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0c, 0xc0, /* ....**..**.. */ + 0x1f, 0x80, /* ...******... */ + 0x33, 0x00, /* ..**..**.... */ + 0x00, 0x00, /* ............ */ + 0x27, 0x80, /* ..*..****... */ + 0x79, 0xc0, /* .****..***.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x79, 0xe0, /* .****..****. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 242 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1c, 0x00, /* ...***...... */ + 0x0f, 0x00, /* ....****.... */ + 0x03, 0x80, /* ......***... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xe0, /* ..*.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0x40, /* .***.....*.. */ + 0x38, 0x80, /* ..***...*... */ + 0x1f, 0x00, /* ...*****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 243 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xe0, /* ..*.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0x40, /* .***.....*.. */ + 0x38, 0x80, /* ..***...*... */ + 0x1f, 0x00, /* ...*****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 244 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xe0, /* ..*.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0x40, /* .***.....*.. */ + 0x38, 0x80, /* ..***...*... */ + 0x1f, 0x00, /* ...*****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 245 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0c, 0xc0, /* ....**..**.. */ + 0x1f, 0x80, /* ...******... */ + 0x33, 0x00, /* ..**..**.... */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xe0, /* ..*.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0x40, /* .***.....*.. */ + 0x38, 0x80, /* ..***...*... */ + 0x1f, 0x00, /* ...*****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 246 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0x80, /* ....*****... */ + 0x11, 0xc0, /* ...*...***.. */ + 0x20, 0xe0, /* ..*.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x70, 0x40, /* .***.....*.. */ + 0x38, 0x80, /* ..***...*... */ + 0x1f, 0x00, /* ...*****.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 247 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x7f, 0xe0, /* .**********. */ + 0x7f, 0xe0, /* .**********. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 248 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x0f, 0xe0, /* ....*******. */ + 0x11, 0xc0, /* ...*...***.. */ + 0x21, 0xe0, /* ..*....****. */ + 0x63, 0x60, /* .**...**.**. */ + 0x66, 0x60, /* .**..**..**. */ + 0x66, 0x60, /* .**..**..**. */ + 0x6c, 0x60, /* .**.**...**. */ + 0x78, 0x40, /* .****....*.. */ + 0x38, 0x80, /* ..***...*... */ + 0x7f, 0x00, /* .*******.... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 249 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x1c, 0x00, /* ...***...... */ + 0x0f, 0x00, /* ....****.... */ + 0x03, 0x80, /* ......***... */ + 0x00, 0x00, /* ............ */ + 0x79, 0xe0, /* .****..****. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0x60, /* ...****..**. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 250 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0x00, 0x00, /* ............ */ + 0x79, 0xe0, /* .****..****. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0x60, /* ...****..**. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 251 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x06, 0x00, /* .....**..... */ + 0x0f, 0x00, /* ....****.... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x79, 0xe0, /* .****..****. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0x60, /* ...****..**. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 252 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x79, 0xe0, /* .****..****. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x30, 0xc0, /* ..**....**.. */ + 0x39, 0xc0, /* ..***..***.. */ + 0x1e, 0x60, /* ...****..**. */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + + /* 253 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x03, 0x80, /* ......***... */ + 0x0f, 0x00, /* ....****.... */ + 0x1c, 0x00, /* ...***...... */ + 0x00, 0x00, /* ............ */ + 0xf0, 0xf0, /* ****....**** */ + 0x60, 0x20, /* .**.......*. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x18, 0x80, /* ...**...*... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x04, 0x00, /* .....*...... */ + 0x0c, 0x00, /* ....**...... */ + 0x08, 0x00, /* ....*....... */ + 0x78, 0x00, /* .****....... */ + 0x70, 0x00, /* .***........ */ + + /* 254 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xe0, 0x00, /* ***......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x6f, 0x80, /* .**.*****... */ + 0x71, 0xc0, /* .***...***.. */ + 0x60, 0xe0, /* .**.....***. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x60, /* .**......**. */ + 0x60, 0x40, /* .**......*.. */ + 0x70, 0x80, /* .***....*... */ + 0x7f, 0x00, /* .*******.... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0x60, 0x00, /* .**......... */ + 0xf0, 0x00, /* ****........ */ + + /* 255 */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0x19, 0x80, /* ...**..**... */ + 0x19, 0x80, /* ...**..**... */ + 0x00, 0x00, /* ............ */ + 0x00, 0x00, /* ............ */ + 0xf0, 0xf0, /* ****....**** */ + 0x60, 0x20, /* .**.......*. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x30, 0x40, /* ..**.....*.. */ + 0x18, 0x80, /* ...**...*... */ + 0x18, 0x80, /* ...**...*... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x0d, 0x00, /* ....**.*.... */ + 0x06, 0x00, /* .....**..... */ + 0x06, 0x00, /* .....**..... */ + 0x04, 0x00, /* .....*...... */ + 0x0c, 0x00, /* ....**...... */ + 0x08, 0x00, /* ....*....... */ + 0x78, 0x00, /* .****....... */ + 0x70, 0x00, /* .***........ */ +}; From 4ee873797bb4cc289a163182c6db20b122cb0265 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:29:39 +0200 Subject: [PATCH 20/25] ? Edits I completely do not understand --- hacks/glx/xlock-gl-utils.c | 2 +- utils/grabclient.h | 3 ++- utils/utf8wc.c | 7 ++++++- utils/visual-gl.c | 22 ++++++++++++++++++++-- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/hacks/glx/xlock-gl-utils.c b/hacks/glx/xlock-gl-utils.c index 1d349206c..57c7f7b9c 100644 --- a/hacks/glx/xlock-gl-utils.c +++ b/hacks/glx/xlock-gl-utils.c @@ -206,7 +206,7 @@ void glXSwapBuffers (Display *dpy, GLXDrawable win) { egl_data *d = global_egl_kludge; - if (!d) abort(); + if (!d) return; /* Called glXSwapBuffers before glXMakeCurrent? */ if (! eglSwapBuffers (d->egl_display, d->egl_surface)) abort(); } diff --git a/utils/grabclient.h b/utils/grabclient.h index 2b8a65ec6..1edbbe6e4 100644 --- a/utils/grabclient.h +++ b/utils/grabclient.h @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright © 1992-2022 Jamie Zawinski +/* xscreensaver, Copyright © 1992-2025 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 @@ -65,6 +65,7 @@ extern async_load_state *load_image_async_simple (async_load_state *, /* Don't use these: this is how "xscreensaver-getimage" and "grabclient.c" pass the file name around. */ #define XA_XSCREENSAVER_IMAGE_FILENAME "_SCREENSAVER_IMAGE_FILENAME" +#define XA_XSCREENSAVER_IMAGE_TITLE "_SCREENSAVER_IMAGE_TITLE" #define XA_XSCREENSAVER_IMAGE_GEOMETRY "_SCREENSAVER_IMAGE_GEOMETRY" #ifdef HAVE_JWXYZ diff --git a/utils/utf8wc.c b/utils/utf8wc.c index ee96f93e0..584d51cbe 100644 --- a/utils/utf8wc.c +++ b/utils/utf8wc.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright © 2014-2024 Jamie Zawinski +/* xscreensaver, Copyright © 2014-2025 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 @@ -816,6 +816,11 @@ main (int argc, char **argv) URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC URC }, + + { "7.0", /* RFC 9839 */ + /* "\u0089\uDEAD\uD9BF\uDFFF" */ + "\211\355\272\255\355\246\277\355\277\277", + URC URC URC URC }, }; int i; diff --git a/utils/visual-gl.c b/utils/visual-gl.c index 6b394298d..8f4135d4f 100644 --- a/utils/visual-gl.c +++ b/utils/visual-gl.c @@ -58,9 +58,27 @@ get_gl_visual (Screen *screen) EGLConfig egl_config = 0; int egl_major = -1, egl_minor = -1; + /* If you pass in a non-NULL EGLAttrib list to eglGetPlatformDisplay -- + even one with no elements, that is, the single terminator { EGL_NONE } -- + you get the error, "no matching EGL config for X11 visual 0x21". + So it is impossible for us to inform EGL which X11 screen number + is in use, for any weirdos still using Zaphod multi-head. + */ +# if 1 + EGLAttrib *av = NULL; +# else + EGLAttrib av[10]; + int ac = 0; +# ifdef EGL_PLATFORM_X11_SCREEN_KHR + av[ac++] = EGL_PLATFORM_X11_SCREEN_KHR; + av[ac++] = (EGLAttrib) screen_number (screen); +# endif + av[ac] = EGL_NONE; +#endif + /* This is re-used, no need to close it. */ - egl_display = eglGetPlatformDisplay (EGL_PLATFORM_X11_KHR, - (void *) dpy, NULL); + egl_display = eglGetPlatformDisplay (EGL_PLATFORM_X11_KHR, (void *) dpy, av); + if (!egl_display) { fprintf (stderr, "%s: eglGetPlatformDisplay failed\n", progname); From fbd410a849cfc153d77d7353a4827c901b52435a Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 17:29:03 +0200 Subject: [PATCH 21/25] Fix manpages, typos - Misnamed manpages - Forgetting to write hypens as \- in manpages and a couple more --- hacks/ansi-tty.c | 2 +- hacks/binaryhorizon.man | 2 +- hacks/celtic.man | 2 +- hacks/config/endgame.xml | 2 +- hacks/eruption.man | 4 ++-- hacks/glx/atunnel.man | 2 +- hacks/glx/beats.man | 2 +- hacks/glx/cubocteversion.man | 2 +- hacks/glx/noof.man | 2 +- hacks/glx/polyhedra.man | 2 +- hacks/glx/sphereeversion.man | 2 +- hacks/halftone.man | 1 + hacks/m6502.man | 2 +- hacks/metaballs.man | 10 +++++----- hacks/popsquares.man | 2 +- hacks/xscreensaver-getimage-file.man | 2 +- hacks/xscreensaver-getimage-video.man | 2 +- hacks/xscreensaver-getimage.man | 2 +- hacks/xscreensaver-text.man | 2 +- 19 files changed, 24 insertions(+), 23 deletions(-) diff --git a/hacks/ansi-tty.c b/hacks/ansi-tty.c index 5e506ab38..231251d67 100644 --- a/hacks/ansi-tty.c +++ b/hacks/ansi-tty.c @@ -51,7 +51,7 @@ struct tty_state { However, this only applies to cursor coordinates caused by text insertion. Inserting "X" at column 80 lets cursor.x go to 81; but if at column 70 - and you do "move right by 20", the cursot ends up at 80, not 81. Fun! + and you do "move right by 20", the cursor ends up at 80, not 81. Fun! Details: https://github.com/mattiase/wraptest */ diff --git a/hacks/binaryhorizon.man b/hacks/binaryhorizon.man index b909925d7..0ef51b00a 100644 --- a/hacks/binaryhorizon.man +++ b/hacks/binaryhorizon.man @@ -1,6 +1,6 @@ .TH "Binary Horizon" 1 "23-Mar-20" "X Version 11" .SH NAME -binaryhorizon - A system of path tracing particles evolves continuously. +binaryhorizon \- A system of path tracing particles evolves continuously. .SH SYNOPSIS .B binaryhorizon [\-\-fps] diff --git a/hacks/celtic.man b/hacks/celtic.man index a0218c1af..02ce3f5d8 100644 --- a/hacks/celtic.man +++ b/hacks/celtic.man @@ -2,7 +2,7 @@ .SH NAME celtic \- draws celtic cross-stich patterns .SH SYNOPSIS -.B ifs +.B celtic [\-\-display \fIhost:display.screen\fP] [\-\-visual \fIvisual\fP] [\-\-window] diff --git a/hacks/config/endgame.xml b/hacks/config/endgame.xml index 3fabdb331..117094659 100644 --- a/hacks/config/endgame.xml +++ b/hacks/config/endgame.xml @@ -19,7 +19,7 @@ <_description> Black slips out of three mating nets, but the fourth one holds him tight! -A brilliant composition! +A brilliant composition! See also the "Queens" screen saver. diff --git a/hacks/eruption.man b/hacks/eruption.man index 598269baa..553c2e783 100644 --- a/hacks/eruption.man +++ b/hacks/eruption.man @@ -1,8 +1,8 @@ .TH XScreenSaver 1 "" "X Version 11" .SH NAME -Eruption \- eruption of pieces of hot volcanic rock +eruption \- eruption of pieces of hot volcanic rock .SH SYNOPSIS -.B Eruption +.B eruption [\-\-display \fIhost:display.screen\fP] [\-\-visual \fIvisual\fP] [\-\-window] diff --git a/hacks/glx/atunnel.man b/hacks/glx/atunnel.man index 43b8da4b1..785260ae8 100644 --- a/hacks/glx/atunnel.man +++ b/hacks/glx/atunnel.man @@ -2,7 +2,7 @@ .SH NAME atunnel \- hypnotic GL tunnel journey .SH SYNOPSIS -.B sballs +.B atunnel [\-\-display \fIhost:display.screen\fP] [\-\-window] [\-\-root] [\-\-window\-id \fInumber\fP] [\-\-visual \fIvisual\fP] [\-\-delay \fImicroseconds\fP] diff --git a/hacks/glx/beats.man b/hacks/glx/beats.man index 5543403b5..147b3fada 100644 --- a/hacks/glx/beats.man +++ b/hacks/glx/beats.man @@ -1,6 +1,6 @@ .TH XScreenSaver 1 "2020-Feb-04" "X Version 11" .SH NAME -beats - create offset beating figures +beats \- create offset beating figures .SH SYNOPSIS .B beats [\-\-display \fIhost:display.screen\fP] diff --git a/hacks/glx/cubocteversion.man b/hacks/glx/cubocteversion.man index ab65d3895..f25ce1739 100644 --- a/hacks/glx/cubocteversion.man +++ b/hacks/glx/cubocteversion.man @@ -1,6 +1,6 @@ .TH XScreenSaver 1 "" "X Version 11" .SH NAME -cubocteversion - Displays a cuboctahedron eversion. +cubocteversion \- Displays a cuboctahedron eversion. .SH SYNOPSIS .B cubocteversion [\-\-display \fIhost:display.screen\fP] diff --git a/hacks/glx/noof.man b/hacks/glx/noof.man index fbbc2c5e8..d021c7597 100644 --- a/hacks/glx/noof.man +++ b/hacks/glx/noof.man @@ -2,7 +2,7 @@ .SH NAME noof \- draw rotatey patterns .SH SYNOPSIS -.B dangerball +.B noof [\-\-display \fIhost:display.screen\fP] [\-\-visual \fIvisual\fP] [\-\-window] diff --git a/hacks/glx/polyhedra.man b/hacks/glx/polyhedra.man index 0408760f3..9ecb85d82 100644 --- a/hacks/glx/polyhedra.man +++ b/hacks/glx/polyhedra.man @@ -92,7 +92,7 @@ Select a new polyhedron at random. .B + \fIor\fP > Select the next-higher-numbered polyhedron. .TP 12 -.B - \fIor\fP < +.B \- \fIor\fP < Select the next-lower-numbered polyhedron. .TP 12 .B ESC \fIor\fP ^C diff --git a/hacks/glx/sphereeversion.man b/hacks/glx/sphereeversion.man index 9d7814945..a290289ca 100644 --- a/hacks/glx/sphereeversion.man +++ b/hacks/glx/sphereeversion.man @@ -1,6 +1,6 @@ .TH XScreenSaver 1 "" "X Version 11" .SH NAME -sphereeversion - Displays a sphere eversion. +sphereeversion \- Displays a sphere eversion. .SH SYNOPSIS .B sphereeversion [\-\-display \fIhost:display.screen\fP] diff --git a/hacks/halftone.man b/hacks/halftone.man index ca82ea434..e07043464 100644 --- a/hacks/halftone.man +++ b/hacks/halftone.man @@ -56,6 +56,7 @@ The minimum speed of each mass point. Default: 0.001 .TP 8 .B \-\-maxspeed \fInumber\fP The maximum speed of each mass point. Default: 0.02 +.TP 8 .B \-\-delay \fInumber\fP Per-frame delay, in microseconds. Default: 10000 .TP 8 diff --git a/hacks/m6502.man b/hacks/m6502.man index 67e75ffef..21694309c 100644 --- a/hacks/m6502.man +++ b/hacks/m6502.man @@ -1,6 +1,6 @@ .TH XScreenSaver 1 "5-May-2004" "X Version 11" .SH NAME -m6502 - 6502 Microprocessor Emulator +m6502 \- 6502 Microprocessor Emulator .SH SYNOPSIS .B m6502 [\-\-display \fIhost:display.screen\fP] [\-\-foreground \fIcolor\fP] diff --git a/hacks/metaballs.man b/hacks/metaballs.man index d9afcbbd1..85b3016ea 100644 --- a/hacks/metaballs.man +++ b/hacks/metaballs.man @@ -1,8 +1,8 @@ .TH XScreenSaver 1 "" "X Version 11" .SH NAME -MetaBalls \- draws 2D metaballs +metaballs \- draws 2D metaballs .SH SYNOPSIS -.B MetaBalls +.B metaballs [\-\-display \fIhost:display.screen\fP] [\-\-visual \fIvisual\fP] [\-\-window] @@ -37,7 +37,7 @@ Draw on the specified window. Number of Colors. Default: 256. .TP 8 .B \-\-count \fInumber\fP -Number of MetaBalls. 2 - 255. Default: 10. +Number of metaballs. 2 - 255. Default: 10. .TP 8 .B \-\-delay \fInumber\fP Per-frame delay, in microseconds. Default: 5000 (0.005 seconds.). @@ -46,10 +46,10 @@ Per-frame delay, in microseconds. Default: 5000 (0.005 seconds.). Duration. 100 - 3000. Default: 1000. .TP 8 .B \-\-radius \fInumber\fP -MetaBall Radius. 2 - 100. Default: 100. +metaball Radius. 2 - 100. Default: 100. .TP 8 .B \-\-delta \fInumber\fP -MetaBall Movement. 1 - 20. Default: 3. +metaball Movement. 1 - 20. Default: 3. .TP 8 .B \-\-fps Display the current frame rate and CPU load. diff --git a/hacks/popsquares.man b/hacks/popsquares.man index e307edde3..c9106187f 100644 --- a/hacks/popsquares.man +++ b/hacks/popsquares.man @@ -1,6 +1,6 @@ .TH XScreenSaver 1 "" "X Version 11" .SH NAME -popsquares - pop artish pulsing color grid. +popsquares \- pop artish pulsing color grid. .SH SYNOPSIS .B popsquares [\-\-display \fIhost:display.screen\fP] diff --git a/hacks/xscreensaver-getimage-file.man b/hacks/xscreensaver-getimage-file.man index 754e6b116..ebf1d531b 100644 --- a/hacks/xscreensaver-getimage-file.man +++ b/hacks/xscreensaver-getimage-file.man @@ -1,6 +1,6 @@ .TH XScreenSaver 1 "20-Mar-2005 (4.21)" "X Version 11" .SH NAME -xscreensaver-getimage-file - select a random image file for use by screen savers +xscreensaver-getimage-file \- select a random image file for use by screen savers .SH SYNOPSIS .B xscreensaver-getimage-file [\--verbose] diff --git a/hacks/xscreensaver-getimage-video.man b/hacks/xscreensaver-getimage-video.man index 8edf5184a..f2aff6079 100644 --- a/hacks/xscreensaver-getimage-video.man +++ b/hacks/xscreensaver-getimage-video.man @@ -1,6 +1,6 @@ .TH XScreenSaver 1 "20-Mar-2005 (4.21)" "X Version 11" .SH NAME -xscreensaver-getimage-video - grab a video still frame for use by screen savers +xscreensaver-getimage-video \- grab a video still frame for use by screen savers .SH SYNOPSIS .B xscreensaver-getimage-video [\--verbose] diff --git a/hacks/xscreensaver-getimage.man b/hacks/xscreensaver-getimage.man index 155c45c80..62f019055 100644 --- a/hacks/xscreensaver-getimage.man +++ b/hacks/xscreensaver-getimage.man @@ -1,6 +1,6 @@ .TH XScreenSaver 1 "20-Mar-2005 (4.21)" "X Version 11" .SH NAME -xscreensaver-getimage - loads a randomly-selected image onto an X11 Drawable +xscreensaver-getimage \- loads a randomly-selected image onto an X11 Drawable for use by screen savers .SH SYNOPSIS .B xscreensaver-getimage diff --git a/hacks/xscreensaver-text.man b/hacks/xscreensaver-text.man index a56387915..b20f918fd 100644 --- a/hacks/xscreensaver-text.man +++ b/hacks/xscreensaver-text.man @@ -1,6 +1,6 @@ .TH XScreenSaver 1 "20-Mar-2005 (4.21)" "X Version 11" .SH NAME -xscreensaver\-text - prints some text to stdout, for use by screen savers. +xscreensaver\-text \- prints some text to stdout, for use by screen savers. .SH SYNOPSIS .B xscreensaver\-text [\--verbose] From 554fd2aea8d25bd583b5d33381cffb0201e0a330 Mon Sep 17 00:00:00 2001 From: gesh Date: Wed, 3 Dec 2025 18:02:41 +0200 Subject: [PATCH 22/25] trans: Add Georgian translation --- po/ka.po | 10495 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 10495 insertions(+) create mode 100644 po/ka.po diff --git a/po/ka.po b/po/ka.po new file mode 100644 index 000000000..e1a4d1423 --- /dev/null +++ b/po/ka.po @@ -0,0 +1,10495 @@ +# Georgian translation for xscreensaver. +# Copyright (C) 2025 xscreensaver's authors +# This file is distributed under the same license as the xscreensaver package. +# Ekaterine Papava , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: xscreensaver\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-02-21 14:05+0100\n" +"PO-Revision-Date: 2025-09-26 12:56+0200\n" +"Last-Translator: Ekaterine Papava \n" +"Language-Team: Georgian <(nothing)>\n" +"Language: ka\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 3.7\n" + +#: ../driver/demo-Gtk-conf.c:931 +msgid "Browse..." +msgstr "ამორჩევა..." + +#: ../driver/demo-Gtk-conf.c:1117 +msgid "Select file." +msgstr "აირჩიეთ ფაილი." + +#: ../driver/demo-Gtk.c:612 ../driver/demo-Gtk.c:619 +msgid "_OK" +msgstr "_დიახ" + +#: ../driver/demo-Gtk.c:616 +msgid "Launch" +msgstr "გაშვება" + +#: ../driver/demo-Gtk.c:617 ../driver/demo-Gtk.c:618 +msgid "Kill" +msgstr "მოკვლა" + +#: ../driver/demo-Gtk.c:621 ../driver/demo-Gtk.c:1894 ../driver/demo-Gtk.c:2128 +msgid "_Cancel" +msgstr "გაუქმება" + +#: ../driver/demo-Gtk.c:686 ../driver/demo-Gtk.c:726 +msgid "Unknown error!" +msgstr "უცნობი შეცდომა!" + +#: ../driver/demo-Gtk.c:687 ../driver/demo-Gtk.c:727 ../driver/demo-Gtk.c:850 +#: ../driver/demo-Gtk.c:981 ../driver/demo-Gtk.c:1010 ../driver/demo-Gtk.c:1016 +#: ../driver/demo-Gtk.c:1217 ../driver/demo-Gtk.c:2176 +#: ../driver/demo-Gtk.c:2183 ../driver/demo-Gtk.c:4346 +msgid "Error" +msgstr "შეცდომა" + +#: ../driver/demo-Gtk.c:738 ../driver/demo-Gtk.c:4132 +#, c-format +msgid "" +"The XScreenSaver daemon doesn't seem to be running\n" +"on display \"%.25s\". Launch it now?" +msgstr "" +"როგორც ჩანს, ეკრანზე \"%.25s\" XScreenSaver-ის დემონი\n" +"გაშვებული არაა. გავუშვა ის ახლა?" + +#: ../driver/demo-Gtk.c:741 ../driver/demo-Gtk.c:1840 ../driver/demo-Gtk.c:2066 +#: ../driver/demo-Gtk.c:3154 ../driver/demo-Gtk.c:4200 +#: ../driver/demo-Gtk.c:4222 ../driver/demo-Gtk.c:4226 +#: ../driver/demo-Gtk.c:4234 +msgid "Warning" +msgstr "შეტყობინება" + +#: ../driver/demo-Gtk.c:851 +msgid "No Help URL has been specified.\n" +msgstr "დახმარების ბმული მითითებული არაა.\n" + +#: ../driver/demo-Gtk.c:970 +msgid "" +"The xscreensaver daemon did not start up properly.\n" +"\n" +msgstr "" +"XScreenSaver-ის დემონი სწორად არ გაეშვა.\n" +"\n" + +#: ../driver/demo-Gtk.c:975 +msgid "" +"You are running as root. Don't do that. Instead, you should\n" +"log in as a normal user and use `sudo' as necessary." +msgstr "" +"შესული ბრძანდებით, როგორც root. ნუ შვრებით ამას. ამის მაგიერ,\n" +"შედით ჩვეულებრივი მომხმარებლით და გამოიყენეთ 'sudo', როცა ეს დაგჭირდებათ." + +#: ../driver/demo-Gtk.c:979 +msgid "Please check your $PATH and permissions." +msgstr "შეამოწმეთ თქვენი $PATH და თქვენი წვდომები." + +#: ../driver/demo-Gtk.c:1011 +msgid "Couldn't determine init file name!\n" +msgstr "შეუძლებელია init ფაილის სახელის დადგენა!\n" + +#: ../driver/demo-Gtk.c:1015 +#, c-format +msgid "Couldn't write %s\n" +msgstr "%s-ის ჩაწერა შეუძლებელია\n" + +#: ../driver/demo-Gtk.c:1215 +#, c-format +msgid "Unparsable time format: \"%.100s\"\n" +msgstr "არასამუშავებადი დროის ფორმატი: \"%.100s\"\n" + +#: ../driver/demo-Gtk.c:1822 +msgid "Image directory is unset" +msgstr "გამოსახულებების საქაღალდე დაყენებული არაა" + +#: ../driver/demo-Gtk.c:1827 +msgid "Image directory does not exist" +msgstr "გამოსახულებების საქაღალდე არ არსებობს" + +#: ../driver/demo-Gtk.c:1829 +msgid "Image directory is empty" +msgstr "გამოსახულებების საქაღალდე ცარიელია" + +#: ../driver/demo-Gtk.c:1834 +#, c-format +msgid "" +"%.100s:\n" +"\n" +" %.100s\n" +"\n" +"Select the 'Advanced' tab and choose a directory with some\n" +"pictures in it, or you're going to see a lot of boring colorbars!" +msgstr "" +"%.100s:\n" +"\n" +" %.100s\n" +"\n" +"აირჩიეთ 'დამატებით' და აირჩიეთ საქაღალდე, რომლებშიც\n" +"სურათებია და მოსაბეზრებელ პანელებს აღარ დაინახავთ!" + +#: ../driver/demo-Gtk.c:1891 +msgid "XScreenSaver Image Cache" +msgstr "XScreenSaver-ის გამოსახულებების კეში" + +#: ../driver/demo-Gtk.c:1897 +#, c-format +msgid "Populating image cache for \"%.100s\"..." +msgstr "გამოსახულებების კეშის შევსება \"%.100s\"-სთვის..." + +#: ../driver/demo-Gtk.c:2129 +msgid "_Select" +msgstr "_აირჩიეთ" + +#: ../driver/demo-Gtk.c:2175 +#, c-format +msgid "Directory does not exist: \"%.100s\"\n" +msgstr "საქაღალდე არ არსებობს: \"%.100s\"\n" + +#: ../driver/demo-Gtk.c:2182 +#, c-format +msgid "File does not exist: \"%.100s\"\n" +msgstr "ფაილი არ არსებობს: \"%.100s\"\n" + +#: ../driver/demo-Gtk.c:2218 +msgid "Please select the image directory." +msgstr "აირჩიეთ გამოსახულებების საქაღალდე." + +#: ../driver/demo-Gtk.c:2248 +msgid "Please select a text file." +msgstr "აირჩიეთ ტექსტური ფაილი." + +#: ../driver/demo-Gtk.c:2266 +msgid "Please select a text-generating program." +msgstr "აირჩიეთ ტექსტის დამაგენერირებელი პროგრამა." + +#: ../driver/demo-Gtk.c:2445 +msgid "Use" +msgstr "გამოყენება" + +#: ../driver/demo-Gtk.c:2455 +msgid "Screen Saver" +msgstr "ეკრანის დაცვა" + +#: ../driver/demo-Gtk.c:2750 +msgid "Display Power Management (not supported by this display)" +msgstr "ეკრანის კვების მართვა (ამ ეკრანს მიერ მხარდაჭერილი არა)" + +#: ../driver/demo-Gtk.c:2910 +msgid "Restart Daemon" +msgstr "დემონის გადატვირთვა" + +#: ../driver/demo-Gtk.c:2911 +msgid "Launch Daemon" +msgstr "დემონის გაშვება" + +#: ../driver/demo-Gtk.c:2954 +msgid "Blank Screen" +msgstr "ეკრანის გასუფთავება" + +#: ../driver/demo-Gtk.c:2960 +msgid "Screen Saver Disabled" +msgstr "ეკრანის შემნახველის გამორთულია" + +#: ../driver/demo-Gtk.c:2983 +msgid "Preview" +msgstr "მინიატურა" + +#: ../driver/demo-Gtk.c:2996 +#, c-format +msgid "%s: %.100s Settings" +msgstr "%s: %.100s-ის მორგება" + +#: ../driver/demo-Gtk.c:3009 +msgid "Any" +msgstr "ნებისმიერი" + +#: ../driver/demo-Gtk.c:3153 +#, c-format +msgid "file \"%s\" has changed, reloading.\n" +msgstr "ფაილი \"%s\" შეიცვალა. თავიდან ჩატვირთვა.\n" + +#: ../driver/demo-Gtk.c:4142 +#, c-format +msgid "" +"%s is running as user \"%s\" on host \"%s\".\n" +"But the xscreensaver managing display \"%.25s\"\n" +"is running as user \"%s\" on host \"%s\".\n" +"\n" +"Since they are different users, they won't be reading/writing\n" +"the same ~/.xscreensaver file, so %s isn't\n" +"going to work right.\n" +"\n" +"You should either re-run %s as \"%s\", or re-run\n" +"xscreensaver as \"%s\".\n" +"\n" +"Restart the xscreensaver daemon now?\n" +msgstr "" + +#: ../driver/demo-Gtk.c:4166 +#, c-format +msgid "" +"%s is running as user \"%s\" on host \"%s\".\n" +"But the xscreensaver managing display \"%s\"\n" +"is running as user \"%s\" on host \"%s\".\n" +"\n" +"If those two machines don't share a file system (that is,\n" +"if they don't see the same ~%s/.xscreensaver file) then\n" +"%s won't work right.\n" +"\n" +"Restart the daemon on \"%s\" as \"%s\" now?\n" +msgstr "" + +#: ../driver/demo-Gtk.c:4187 +#, c-format +msgid "" +"This is %s version %s.\n" +"But the xscreensaver managing display \"%s\"\n" +"is version %s. This could cause problems.\n" +"\n" +"Restart the xscreensaver daemon now?\n" +msgstr "" + +#: ../driver/demo-Gtk.c:4217 +#, c-format +msgid "" +"The GNOME screen saver daemon (%s) appears to be running.\n" +"It must be stopped for XScreenSaver to work properly.\n" +"\n" +"Stop the \"%s\" daemon now?\n" +msgstr "" + +#: ../driver/demo-Gtk.c:4227 +msgid "" +"The KDE screen saver daemon appears to be running.\n" +"It must be stopped for XScreenSaver to work properly.\n" +"\n" +"Stop the KDE screen saver daemon now?\n" +msgstr "" + +#: ../driver/demo-Gtk.c:4235 +msgid "" +"You are running Wayland rather than the X Window System.\n" +"\n" +"Under Wayland, idle-detection fails when non-X11 programs\n" +"are selected, meaning the screen may blank prematurely.\n" +"Also, locking is impossible.\n" +"\n" +"See the XScreenSaver manual for instructions on\n" +"configuring your system to use X11 instead of Wayland.\n" +msgstr "" + +#: ../driver/demo-Gtk.c:4347 +msgid "no `manualCommand' resource set." +msgstr "რესურსი 'manualCommand' დაყენებული არაა." + +#: ../driver/demo-Gtk.c:4589 ../driver/demo-Gtk.c:4623 +msgid "No description available." +msgstr "აღწერის გარეშე." + +#: ../driver/dialog.c:1056 +#, c-format +msgid "" +"Copyright © 1991-%.4s by\n" +"Jamie Zawinski " +msgstr "" +"Copyright © 1991-%.4s by\n" +"Jamie Zawinski " + +#: ../driver/dialog.c:1377 +msgid "" +"Update available!\n" +"This version is very old.\n" +msgstr "" +"ხელმისაწვდომია განახლება!\n" +"ეს ვერსია ძალიან ძველია.\n" + +#: ../driver/dialog.c:1389 +msgid "PRE-RELEASE VERSION" +msgstr "წინასწარი რელიზი" + +#: ../driver/dialog.c:1426 +msgid "" +"DEBUG MODE:\n" +"All keystrokes are being logged to stderr.\n" +msgstr "" +"გამართვის რეჟიმი:\n" +"ყველა ღილაკის დაწოლა stderr-ზე გამოჩნდება.\n" + +#: ../driver/dialog.c:1475 +msgid "Username:" +msgstr "მომხმარებელი:" + +#: ../driver/dialog.c:1506 +msgid "Checking..." +msgstr "შემოწმება…" + +#: ../driver/dialog.c:1586 +msgid "Settings" +msgstr "მორგება" + +#: ../driver/dialog.c:1601 +msgid "Help" +msgstr "დახმარება" + +#: ../driver/dialog.c:1615 +msgid "New Login" +msgstr "ახალი შესვლის დეტალები" + +#: ../driver/dialog.c:1627 +msgid "OK" +msgstr "დიახ" + +#: ../driver/dialog.c:2597 +msgid "Password initialization failed" +msgstr "პაროლის ინიციალიზაცია ჩავარდა" + +#: ../driver/dialog.c:2599 +msgid "Authentication failed (Caps Lock?)" +msgstr "ავთენტკაცია ჩავარდა (Caps Lock?)" + +#: ../driver/dialog.c:2601 +msgid "Authentication failed!" +msgstr "ავთენტიკაციის შეცდომა!" + +#: ../driver/dialog.c:2621 +#, c-format +msgid "%d days ago" +msgstr "%d დღის წინ" + +#: ../driver/dialog.c:2622 +#, c-format +msgid "%d hours ago" +msgstr "%d საათის წინ" + +#: ../driver/dialog.c:2623 +#, c-format +msgid "%d minutes ago" +msgstr "%d წუთის წინ" + +#: ../driver/dialog.c:2624 +#, c-format +msgid "just now" +msgstr "ახლახანს" + +#: ../driver/dialog.c:2627 +#, c-format +msgid "There has been 1 failed login attempt, %s." +msgstr "1 ჩავარდნილი შესვლის მცდელობა. %s." + +#: ../driver/dialog.c:2630 +#, c-format +msgid "There have been %d failed login attempts, oldest %s." +msgstr "%d ჩავარდნილი შესვლის შეცდომა. უძველესი: %s." + +#: ../driver/subprocs.c:587 +msgid "is not installed" +msgstr "დაყენებული არაა" + +#: ../driver/subprocs.c:589 +#, c-format +msgid "crashed with status %d" +msgstr "დასრულდა ავარიულად, სტატუსით %d" + +#. Expected notification after we killed it. +#: ../driver/subprocs.c:606 +#, c-format +msgid "exited normally with %.100s" +msgstr "გამოვიდა ნორმალურად, სტატუსით %.100s" + +#. Unexpected signal. +#: ../driver/subprocs.c:615 +#, c-format +msgid "crashed with %.100s" +msgstr "ავარიულად დასრულდა, %.100s-ით" + +#. Didn't exit, signal or stop; is this even possible? +#: ../driver/subprocs.c:636 +#, c-format +msgid "crashed mysteriously" +msgstr "ავარიულად დასრულდა, მიზეზების გარეშე" + +#: ../driver/xscreensaver-settings.desktop.in.h:1 +msgid "XScreenSaver Settings" +msgstr "XScreenSaver-ის მორგება" + +#: ../driver/xscreensaver-settings.desktop.in.h:2 +msgid "Change screensaver properties" +msgstr "ეკრანის დამცველის მორგება" + +#: ../driver/xscreensaver.desktop.in.h:1 +msgid "XScreenSaver" +msgstr "XScreenSaver" + +#: ../driver/xscreensaver.desktop.in.h:2 +msgid "XScreenSaver daemon: screen saver and locker" +msgstr "დემონი XScreenSaver: ეკრანის შემნახველი და დამბლოკველი" + +#: ../hacks/config/abstractile.xml.h:1 +msgid "Abstractile" +msgstr "აბსტრაქტული" + +#: ../hacks/config/abstractile.xml.h:2 ../hacks/config/anemone.xml.h:2 +#: ../hacks/config/apollonian.xml.h:10 ../hacks/config/atlantis.xml.h:5 +#: ../hacks/config/attraction.xml.h:24 ../hacks/config/blitspin.xml.h:2 +#: ../hacks/config/boing.xml.h:5 ../hacks/config/bouncingcow.xml.h:5 +#: ../hacks/config/boxed.xml.h:5 ../hacks/config/carousel.xml.h:5 +#: ../hacks/config/ccurve.xml.h:5 ../hacks/config/chompytower.xml.h:5 +#: ../hacks/config/circuit.xml.h:8 ../hacks/config/cityflow.xml.h:9 +#: ../hacks/config/companioncube.xml.h:5 ../hacks/config/covid19.xml.h:5 +#: ../hacks/config/crumbler.xml.h:5 ../hacks/config/cube21.xml.h:8 +#: ../hacks/config/cubenetic.xml.h:17 ../hacks/config/cubestack.xml.h:5 +#: ../hacks/config/cubestorm.xml.h:5 ../hacks/config/cubetwist.xml.h:5 +#: ../hacks/config/cubicgrid.xml.h:5 ../hacks/config/dangerball.xml.h:5 +#: ../hacks/config/deepstars.xml.h:5 ../hacks/config/discoball.xml.h:5 +#: ../hacks/config/dymaxionmap.xml.h:5 ../hacks/config/energystream.xml.h:2 +#: ../hacks/config/eruption.xml.h:10 ../hacks/config/esper.xml.h:5 +#: ../hacks/config/fliptext.xml.h:5 ../hacks/config/flyingtoasters.xml.h:5 +#: ../hacks/config/fontglide.xml.h:5 ../hacks/config/fuzzyflakes.xml.h:5 +#: ../hacks/config/gears.xml.h:5 ../hacks/config/geodesic.xml.h:14 +#: ../hacks/config/gflux.xml.h:5 ../hacks/config/gibson.xml.h:5 +#: ../hacks/config/glcells.xml.h:25 ../hacks/config/glknots.xml.h:5 +#: ../hacks/config/glmatrix.xml.h:8 ../hacks/config/glsnake.xml.h:11 +#: ../hacks/config/goop.xml.h:5 ../hacks/config/gravitywell.xml.h:5 +#: ../hacks/config/handsy.xml.h:5 ../hacks/config/headroom.xml.h:5 +#: ../hacks/config/hexadrop.xml.h:5 ../hacks/config/hexstrut.xml.h:5 +#: ../hacks/config/hilbert.xml.h:8 ../hacks/config/hydrostat.xml.h:5 +#: ../hacks/config/hyperball.xml.h:9 ../hacks/config/hypercube.xml.h:9 +#: ../hacks/config/hypnowheel.xml.h:2 ../hacks/config/interference.xml.h:5 +#: ../hacks/config/jigglypuff.xml.h:14 ../hacks/config/jigsaw.xml.h:5 +#: ../hacks/config/juggle.xml.h:5 ../hacks/config/juggler3d.xml.h:5 +#: ../hacks/config/kaleidocycle.xml.h:8 ../hacks/config/mapscroller.xml.h:5 +#: ../hacks/config/maze3d.xml.h:2 ../hacks/config/moebiusgears.xml.h:5 +#: ../hacks/config/nakagin.xml.h:5 ../hacks/config/peepers.xml.h:5 +#: ../hacks/config/penetrate.xml.h:2 ../hacks/config/petri.xml.h:16 +#: ../hacks/config/phosphor.xml.h:6 ../hacks/config/photopile.xml.h:12 +#: ../hacks/config/piecewise.xml.h:8 ../hacks/config/pinion.xml.h:5 +#: ../hacks/config/polyhedra.xml.h:5 ../hacks/config/pong.xml.h:2 +#: ../hacks/config/pyro.xml.h:2 ../hacks/config/quasicrystal.xml.h:5 +#: ../hacks/config/raverhoop.xml.h:11 ../hacks/config/razzledazzle.xml.h:5 +#: ../hacks/config/rocks.xml.h:8 ../hacks/config/rubik.xml.h:6 +#: ../hacks/config/rubikblocks.xml.h:8 ../hacks/config/skytentacles.xml.h:15 +#: ../hacks/config/slidescreen.xml.h:11 ../hacks/config/sonar.xml.h:5 +#: ../hacks/config/speedmine.xml.h:5 ../hacks/config/splitflap.xml.h:5 +#: ../hacks/config/squirtorus.xml.h:5 ../hacks/config/superquadrics.xml.h:5 +#: ../hacks/config/tangram.xml.h:8 ../hacks/config/topblock.xml.h:5 +#: ../hacks/config/tronbit.xml.h:5 ../hacks/config/twang.xml.h:8 +#: ../hacks/config/unicrud.xml.h:5 ../hacks/config/unknownpleasures.xml.h:8 +#: ../hacks/config/vigilance.xml.h:5 ../hacks/config/voronoi.xml.h:2 +#: ../hacks/config/winduprobot.xml.h:5 ../hacks/config/wormhole.xml.h:5 +#: ../hacks/config/xjack.xml.h:2 +msgid "Slow" +msgstr "ნელი" + +#: ../hacks/config/abstractile.xml.h:3 ../hacks/config/anemone.xml.h:3 +#: ../hacks/config/apollonian.xml.h:11 ../hacks/config/attraction.xml.h:25 +#: ../hacks/config/boing.xml.h:6 ../hacks/config/boxed.xml.h:6 +#: ../hacks/config/covid19.xml.h:6 ../hacks/config/crumbler.xml.h:6 +#: ../hacks/config/cubestorm.xml.h:6 ../hacks/config/cubicgrid.xml.h:6 +#: ../hacks/config/deepstars.xml.h:6 ../hacks/config/discoball.xml.h:6 +#: ../hacks/config/energystream.xml.h:3 ../hacks/config/esper.xml.h:6 +#: ../hacks/config/fliptext.xml.h:6 ../hacks/config/fontglide.xml.h:6 +#: ../hacks/config/fuzzyflakes.xml.h:6 ../hacks/config/gears.xml.h:6 +#: ../hacks/config/glknots.xml.h:6 ../hacks/config/goop.xml.h:6 +#: ../hacks/config/gravitywell.xml.h:6 ../hacks/config/handsy.xml.h:6 +#: ../hacks/config/hexadrop.xml.h:6 ../hacks/config/hexstrut.xml.h:6 +#: ../hacks/config/hilbert.xml.h:11 ../hacks/config/hypnowheel.xml.h:5 +#: ../hacks/config/jigsaw.xml.h:6 ../hacks/config/juggle.xml.h:6 +#: ../hacks/config/juggler3d.xml.h:6 ../hacks/config/kaleidocycle.xml.h:9 +#: ../hacks/config/maze3d.xml.h:3 ../hacks/config/moebiusgears.xml.h:6 +#: ../hacks/config/peepers.xml.h:6 ../hacks/config/polyhedra.xml.h:6 +#: ../hacks/config/quasicrystal.xml.h:6 ../hacks/config/razzledazzle.xml.h:6 +#: ../hacks/config/skytentacles.xml.h:18 ../hacks/config/sonar.xml.h:6 +#: ../hacks/config/splitflap.xml.h:6 ../hacks/config/tessellimage.xml.h:6 +#: ../hacks/config/unknownpleasures.xml.h:9 ../hacks/config/vigilance.xml.h:6 +#: ../hacks/config/xjack.xml.h:3 +msgid "Speed" +msgstr "სიჩქარე" + +#: ../hacks/config/abstractile.xml.h:4 ../hacks/config/anemone.xml.h:4 +#: ../hacks/config/apollonian.xml.h:12 ../hacks/config/atlantis.xml.h:7 +#: ../hacks/config/attraction.xml.h:26 ../hacks/config/blitspin.xml.h:4 +#: ../hacks/config/boing.xml.h:7 ../hacks/config/bouncingcow.xml.h:7 +#: ../hacks/config/boxed.xml.h:7 ../hacks/config/carousel.xml.h:7 +#: ../hacks/config/ccurve.xml.h:7 ../hacks/config/chompytower.xml.h:7 +#: ../hacks/config/circuit.xml.h:10 ../hacks/config/cityflow.xml.h:11 +#: ../hacks/config/companioncube.xml.h:7 ../hacks/config/covid19.xml.h:7 +#: ../hacks/config/crumbler.xml.h:7 ../hacks/config/cube21.xml.h:10 +#: ../hacks/config/cubenetic.xml.h:19 ../hacks/config/cubestack.xml.h:7 +#: ../hacks/config/cubestorm.xml.h:7 ../hacks/config/cubetwist.xml.h:7 +#: ../hacks/config/cubicgrid.xml.h:7 ../hacks/config/dangerball.xml.h:7 +#: ../hacks/config/deepstars.xml.h:7 ../hacks/config/discoball.xml.h:7 +#: ../hacks/config/dymaxionmap.xml.h:7 ../hacks/config/energystream.xml.h:4 +#: ../hacks/config/eruption.xml.h:12 ../hacks/config/esper.xml.h:7 +#: ../hacks/config/fliptext.xml.h:7 ../hacks/config/flyingtoasters.xml.h:7 +#: ../hacks/config/fontglide.xml.h:7 ../hacks/config/fuzzyflakes.xml.h:7 +#: ../hacks/config/gears.xml.h:7 ../hacks/config/geodesic.xml.h:16 +#: ../hacks/config/gflux.xml.h:7 ../hacks/config/gibson.xml.h:7 +#: ../hacks/config/glknots.xml.h:7 ../hacks/config/glmatrix.xml.h:10 +#: ../hacks/config/glsnake.xml.h:13 ../hacks/config/goop.xml.h:7 +#: ../hacks/config/gravitywell.xml.h:7 ../hacks/config/handsy.xml.h:7 +#: ../hacks/config/headroom.xml.h:7 ../hacks/config/hexadrop.xml.h:7 +#: ../hacks/config/hexstrut.xml.h:7 ../hacks/config/hilbert.xml.h:10 +#: ../hacks/config/hydrostat.xml.h:7 ../hacks/config/hyperball.xml.h:11 +#: ../hacks/config/hypercube.xml.h:11 ../hacks/config/hypnowheel.xml.h:4 +#: ../hacks/config/interference.xml.h:7 ../hacks/config/jigglypuff.xml.h:16 +#: ../hacks/config/jigsaw.xml.h:7 ../hacks/config/juggle.xml.h:7 +#: ../hacks/config/juggler3d.xml.h:7 ../hacks/config/kaleidocycle.xml.h:10 +#: ../hacks/config/mapscroller.xml.h:7 ../hacks/config/maze3d.xml.h:4 +#: ../hacks/config/moebiusgears.xml.h:7 ../hacks/config/nakagin.xml.h:7 +#: ../hacks/config/peepers.xml.h:7 ../hacks/config/penetrate.xml.h:4 +#: ../hacks/config/petri.xml.h:18 ../hacks/config/phosphor.xml.h:8 +#: ../hacks/config/photopile.xml.h:14 ../hacks/config/piecewise.xml.h:10 +#: ../hacks/config/pinion.xml.h:7 ../hacks/config/polyhedra.xml.h:7 +#: ../hacks/config/pong.xml.h:4 ../hacks/config/pyro.xml.h:4 +#: ../hacks/config/quasicrystal.xml.h:7 ../hacks/config/raverhoop.xml.h:13 +#: ../hacks/config/razzledazzle.xml.h:7 ../hacks/config/rocks.xml.h:10 +#: ../hacks/config/rubik.xml.h:8 ../hacks/config/rubikblocks.xml.h:10 +#: ../hacks/config/skytentacles.xml.h:17 ../hacks/config/slidescreen.xml.h:13 +#: ../hacks/config/sonar.xml.h:7 ../hacks/config/speedmine.xml.h:7 +#: ../hacks/config/splitflap.xml.h:7 ../hacks/config/squirtorus.xml.h:7 +#: ../hacks/config/starwars.xml.h:5 ../hacks/config/superquadrics.xml.h:7 +#: ../hacks/config/tangram.xml.h:10 ../hacks/config/topblock.xml.h:7 +#: ../hacks/config/tronbit.xml.h:7 ../hacks/config/unicrud.xml.h:7 +#: ../hacks/config/unknownpleasures.xml.h:10 ../hacks/config/vigilance.xml.h:7 +#: ../hacks/config/voronoi.xml.h:4 ../hacks/config/winduprobot.xml.h:7 +#: ../hacks/config/wormhole.xml.h:7 ../hacks/config/xjack.xml.h:4 +msgid "Fast" +msgstr "სწრაფი" + +#: ../hacks/config/abstractile.xml.h:5 ../hacks/config/ccurve.xml.h:2 +#: ../hacks/config/flame.xml.h:5 ../hacks/config/maze.xml.h:13 +msgid "0 seconds" +msgstr "0 წამი" + +#: ../hacks/config/abstractile.xml.h:6 ../hacks/config/boxed.xml.h:17 +#: ../hacks/config/celtic.xml.h:6 ../hacks/config/coral.xml.h:6 +#: ../hacks/config/cube21.xml.h:22 ../hacks/config/epicycle.xml.h:9 +#: ../hacks/config/flame.xml.h:6 ../hacks/config/glcells.xml.h:6 +#: ../hacks/config/helix.xml.h:6 ../hacks/config/imsmap.xml.h:6 +#: ../hacks/config/rorschach.xml.h:9 ../hacks/config/rubikblocks.xml.h:16 +#: ../hacks/config/tangram.xml.h:6 ../hacks/config/xlyap.xml.h:6 +#: ../hacks/config/xspirograph.xml.h:6 +msgid "Linger" +msgstr "დაყოვნება" + +#: ../hacks/config/abstractile.xml.h:7 ../hacks/config/voronoi.xml.h:16 +msgid "60 seconds" +msgstr "60 წამი" + +#: ../hacks/config/abstractile.xml.h:8 +msgid "Random tile layout" +msgstr "ფილების შემთხვევითი განლაგება" + +#: ../hacks/config/abstractile.xml.h:9 +msgid "Flat tiles" +msgstr "ბრტყელი ფილები" + +#: ../hacks/config/abstractile.xml.h:10 +msgid "Thin tiles" +msgstr "თხელი ფილები" + +#: ../hacks/config/abstractile.xml.h:11 +msgid "Outline tiles" +msgstr "კონტურული ფილები" + +#: ../hacks/config/abstractile.xml.h:12 +msgid "Block tiles" +msgstr "ბლოკური ფილები" + +#: ../hacks/config/abstractile.xml.h:13 +msgid "Neon tiles" +msgstr "ნეონის ფილები" + +#: ../hacks/config/abstractile.xml.h:14 +msgid "Tiled tiles" +msgstr "კუსებრი ფილები" + +#: ../hacks/config/abstractile.xml.h:15 ../hacks/config/anemone.xml.h:16 +#: ../hacks/config/anemotaxis.xml.h:12 ../hacks/config/ant.xml.h:22 +#: ../hacks/config/antinspect.xml.h:5 ../hacks/config/antmaze.xml.h:5 +#: ../hacks/config/antspotlight.xml.h:5 ../hacks/config/apollonian.xml.h:13 +#: ../hacks/config/apple2.xml.h:9 ../hacks/config/atlantis.xml.h:19 +#: ../hacks/config/attraction.xml.h:31 ../hacks/config/atunnel.xml.h:8 +#: ../hacks/config/barcode.xml.h:9 ../hacks/config/beats.xml.h:16 +#: ../hacks/config/binaryhorizon.xml.h:14 ../hacks/config/blaster.xml.h:10 +#: ../hacks/config/blinkbox.xml.h:12 ../hacks/config/blitspin.xml.h:9 +#: ../hacks/config/blocktube.xml.h:11 ../hacks/config/boing.xml.h:14 +#: ../hacks/config/bouboule.xml.h:11 ../hacks/config/bouncingcow.xml.h:13 +#: ../hacks/config/boxed.xml.h:23 ../hacks/config/boxfit.xml.h:15 +#: ../hacks/config/braid.xml.h:13 ../hacks/config/bubble3d.xml.h:11 +#: ../hacks/config/bubbles.xml.h:11 ../hacks/config/bumps.xml.h:8 +#: ../hacks/config/cage.xml.h:6 ../hacks/config/carousel.xml.h:18 +#: ../hacks/config/ccurve.xml.h:11 ../hacks/config/celtic.xml.h:9 +#: ../hacks/config/chompytower.xml.h:15 ../hacks/config/circuit.xml.h:14 +#: ../hacks/config/cityflow.xml.h:17 ../hacks/config/cloudlife.xml.h:12 +#: ../hacks/config/companioncube.xml.h:14 ../hacks/config/compass.xml.h:5 +#: ../hacks/config/coral.xml.h:14 ../hacks/config/covid19.xml.h:14 +#: ../hacks/config/crackberg.xml.h:18 ../hacks/config/critical.xml.h:8 +#: ../hacks/config/crumbler.xml.h:15 ../hacks/config/crystal.xml.h:14 +#: ../hacks/config/cube21.xml.h:26 ../hacks/config/cubenetic.xml.h:26 +#: ../hacks/config/cubestack.xml.h:16 ../hacks/config/cubestorm.xml.h:20 +#: ../hacks/config/cubetwist.xml.h:18 ../hacks/config/cubicgrid.xml.h:12 +#: ../hacks/config/cwaves.xml.h:9 ../hacks/config/cynosure.xml.h:11 +#: ../hacks/config/dangerball.xml.h:14 ../hacks/config/decayscreen.xml.h:23 +#: ../hacks/config/deco.xml.h:14 ../hacks/config/deepstars.xml.h:9 +#: ../hacks/config/deluxe.xml.h:15 ../hacks/config/demon.xml.h:15 +#: ../hacks/config/discoball.xml.h:14 ../hacks/config/discrete.xml.h:11 +#: ../hacks/config/distort.xml.h:19 ../hacks/config/dnalogo.xml.h:9 +#: ../hacks/config/drift.xml.h:11 ../hacks/config/dymaxionmap.xml.h:16 +#: ../hacks/config/endgame.xml.h:6 ../hacks/config/energystream.xml.h:7 +#: ../hacks/config/engine.xml.h:19 ../hacks/config/epicycle.xml.h:13 +#: ../hacks/config/eruption.xml.h:22 ../hacks/config/esper.xml.h:9 +#: ../hacks/config/etruscanvenus.xml.h:42 ../hacks/config/euler2d.xml.h:14 +#: ../hacks/config/extrusion.xml.h:16 ../hacks/config/fadeplot.xml.h:14 +#: ../hacks/config/fiberlamp.xml.h:11 ../hacks/config/filmleader.xml.h:9 +#: ../hacks/config/fireworkx.xml.h:10 ../hacks/config/flag.xml.h:12 +#: ../hacks/config/flame.xml.h:14 ../hacks/config/flipflop.xml.h:14 +#: ../hacks/config/flipscreen3d.xml.h:6 ../hacks/config/fliptext.xml.h:15 +#: ../hacks/config/flow.xml.h:21 ../hacks/config/fluidballs.xml.h:22 +#: ../hacks/config/flurry.xml.h:2 ../hacks/config/flyingtoasters.xml.h:15 +#: ../hacks/config/fontglide.xml.h:16 ../hacks/config/forest.xml.h:8 +#: ../hacks/config/fuzzyflakes.xml.h:12 ../hacks/config/galaxy.xml.h:13 +#: ../hacks/config/gears.xml.h:14 ../hacks/config/geodesic.xml.h:10 +#: ../hacks/config/geodesicgears.xml.h:13 ../hacks/config/gflux.xml.h:19 +#: ../hacks/config/gibson.xml.h:15 ../hacks/config/glblur.xml.h:17 +#: ../hacks/config/glcells.xml.h:32 ../hacks/config/gleidescope.xml.h:14 +#: ../hacks/config/glforestfire.xml.h:16 ../hacks/config/glhanoi.xml.h:16 +#: ../hacks/config/glknots.xml.h:24 ../hacks/config/glmatrix.xml.h:20 +#: ../hacks/config/glplanet.xml.h:19 ../hacks/config/glschool.xml.h:17 +#: ../hacks/config/glslideshow.xml.h:20 ../hacks/config/glsnake.xml.h:18 +#: ../hacks/config/gltext.xml.h:19 ../hacks/config/goop.xml.h:13 +#: ../hacks/config/grav.xml.h:12 ../hacks/config/greynetic.xml.h:6 +#: ../hacks/config/halftone.xml.h:17 ../hacks/config/halo.xml.h:14 +#: ../hacks/config/handsy.xml.h:23 ../hacks/config/headroom.xml.h:19 +#: ../hacks/config/helix.xml.h:8 ../hacks/config/hexadrop.xml.h:22 +#: ../hacks/config/hexstrut.xml.h:17 ../hacks/config/hilbert.xml.h:20 +#: ../hacks/config/hopalong.xml.h:23 ../hacks/config/hydrostat.xml.h:29 +#: ../hacks/config/hyperball.xml.h:8 ../hacks/config/hypercube.xml.h:8 +#: ../hacks/config/hypertorus.xml.h:5 ../hacks/config/hypnowheel.xml.h:8 +#: ../hacks/config/ifs.xml.h:68 ../hacks/config/imsmap.xml.h:18 +#: ../hacks/config/interaggregate.xml.h:8 ../hacks/config/interference.xml.h:21 +#: ../hacks/config/intermomentary.xml.h:8 ../hacks/config/jigglypuff.xml.h:10 +#: ../hacks/config/jigsaw.xml.h:15 ../hacks/config/juggle.xml.h:21 +#: ../hacks/config/juggler3d.xml.h:20 ../hacks/config/julia.xml.h:14 +#: ../hacks/config/kaleidescope.xml.h:12 ../hacks/config/kaleidocycle.xml.h:21 +#: ../hacks/config/klein.xml.h:47 ../hacks/config/kumppa.xml.h:7 +#: ../hacks/config/lament.xml.h:7 ../hacks/config/laser.xml.h:12 +#: ../hacks/config/lavalite.xml.h:16 ../hacks/config/lcdscrub.xml.h:7 +#: ../hacks/config/lightning.xml.h:8 ../hacks/config/lisa.xml.h:16 +#: ../hacks/config/lissie.xml.h:15 ../hacks/config/lmorph.xml.h:17 +#: ../hacks/config/lockward.xml.h:9 ../hacks/config/loop.xml.h:12 +#: ../hacks/config/m6502.xml.h:3 ../hacks/config/mapscroller.xml.h:64 +#: ../hacks/config/marbling.xml.h:10 ../hacks/config/maze.xml.h:12 +#: ../hacks/config/maze3d.xml.h:10 ../hacks/config/memscroller.xml.h:9 +#: ../hacks/config/menger.xml.h:19 ../hacks/config/metaballs.xml.h:16 +#: ../hacks/config/mirrorblob.xml.h:25 ../hacks/config/mismunch.xml.h:13 +#: ../hacks/config/moebius.xml.h:7 ../hacks/config/moebiusgears.xml.h:14 +#: ../hacks/config/moire.xml.h:11 ../hacks/config/moire2.xml.h:9 +#: ../hacks/config/molecule.xml.h:15 ../hacks/config/morph3d.xml.h:11 +#: ../hacks/config/mountain.xml.h:11 ../hacks/config/munch.xml.h:16 +#: ../hacks/config/nakagin.xml.h:12 ../hacks/config/nerverot.xml.h:21 +#: ../hacks/config/noof.xml.h:5 ../hacks/config/noseguy.xml.h:2 +#: ../hacks/config/pacman.xml.h:6 ../hacks/config/pedal.xml.h:8 +#: ../hacks/config/peepers.xml.h:17 ../hacks/config/penetrate.xml.h:8 +#: ../hacks/config/penrose.xml.h:12 ../hacks/config/petri.xml.h:5 +#: ../hacks/config/phosphor.xml.h:13 ../hacks/config/photopile.xml.h:22 +#: ../hacks/config/piecewise.xml.h:15 ../hacks/config/pinion.xml.h:16 +#: ../hacks/config/pipes.xml.h:20 ../hacks/config/polyhedra.xml.h:168 +#: ../hacks/config/polyominoes.xml.h:12 ../hacks/config/polytopes.xml.h:18 +#: ../hacks/config/pong.xml.h:9 ../hacks/config/popsquares.xml.h:21 +#: ../hacks/config/projectiveplane.xml.h:45 ../hacks/config/providence.xml.h:7 +#: ../hacks/config/pulsar.xml.h:14 ../hacks/config/pyro.xml.h:14 +#: ../hacks/config/qix.xml.h:24 ../hacks/config/quasicrystal.xml.h:13 +#: ../hacks/config/queens.xml.h:6 ../hacks/config/raverhoop.xml.h:20 +#: ../hacks/config/razzledazzle.xml.h:20 ../hacks/config/ripples.xml.h:18 +#: ../hacks/config/rocks.xml.h:16 ../hacks/config/romanboy.xml.h:43 +#: ../hacks/config/rorschach.xml.h:11 ../hacks/config/rotor.xml.h:13 +#: ../hacks/config/rotzoomer.xml.h:15 ../hacks/config/rubik.xml.h:11 +#: ../hacks/config/rubikblocks.xml.h:20 ../hacks/config/sballs.xml.h:16 +#: ../hacks/config/scooter.xml.h:17 ../hacks/config/shadebobs.xml.h:13 +#: ../hacks/config/sierpinski.xml.h:13 ../hacks/config/sierpinski3d.xml.h:10 +#: ../hacks/config/skytentacles.xml.h:25 ../hacks/config/slidescreen.xml.h:18 +#: ../hacks/config/slip.xml.h:13 ../hacks/config/sonar.xml.h:25 +#: ../hacks/config/speedmine.xml.h:17 ../hacks/config/sphere.xml.h:8 +#: ../hacks/config/sphereeversion.xml.h:38 +#: ../hacks/config/spheremonics.xml.h:22 ../hacks/config/spiral.xml.h:11 +#: ../hacks/config/splitflap.xml.h:25 ../hacks/config/splodesic.xml.h:11 +#: ../hacks/config/spotlight.xml.h:11 ../hacks/config/sproingies.xml.h:9 +#: ../hacks/config/squiral.xml.h:19 ../hacks/config/squirtorus.xml.h:12 +#: ../hacks/config/stairs.xml.h:5 ../hacks/config/starfish.xml.h:17 +#: ../hacks/config/starwars.xml.h:15 ../hacks/config/stonerview.xml.h:7 +#: ../hacks/config/strange.xml.h:23 ../hacks/config/substrate.xml.h:19 +#: ../hacks/config/superquadrics.xml.h:13 ../hacks/config/surfaces.xml.h:27 +#: ../hacks/config/swirl.xml.h:10 ../hacks/config/t3d.xml.h:15 +#: ../hacks/config/tangram.xml.h:16 ../hacks/config/tessellimage.xml.h:19 +#: ../hacks/config/testx11.xml.h:2 ../hacks/config/thornbird.xml.h:11 +#: ../hacks/config/timetunnel.xml.h:8 ../hacks/config/topblock.xml.h:24 +#: ../hacks/config/triangle.xml.h:8 ../hacks/config/tronbit.xml.h:11 +#: ../hacks/config/truchet.xml.h:5 ../hacks/config/twang.xml.h:18 +#: ../hacks/config/unicrud.xml.h:10 ../hacks/config/unknownpleasures.xml.h:17 +#: ../hacks/config/vermiculate.xml.h:5 ../hacks/config/vfeedback.xml.h:9 +#: ../hacks/config/vidwhacker.xml.h:5 ../hacks/config/vines.xml.h:8 +#: ../hacks/config/voronoi.xml.h:11 ../hacks/config/wander.xml.h:13 +#: ../hacks/config/webcollage.xml.h:11 ../hacks/config/whirlwindwarp.xml.h:8 +#: ../hacks/config/whirlygig.xml.h:31 ../hacks/config/winduprobot.xml.h:22 +#: ../hacks/config/worm.xml.h:10 ../hacks/config/wormhole.xml.h:11 +#: ../hacks/config/xanalogtv.xml.h:2 ../hacks/config/xflame.xml.h:6 +#: ../hacks/config/xjack.xml.h:5 ../hacks/config/xlyap.xml.h:8 +#: ../hacks/config/xmatrix.xml.h:21 ../hacks/config/xrayswarm.xml.h:5 +#: ../hacks/config/xspirograph.xml.h:9 ../hacks/config/zoom.xml.h:15 +msgid "Show frame rate" +msgstr "კადრების სიხშირის ჩვენება" + +#: ../hacks/config/abstractile.xml.h:16 +msgid "" +"Mosaic patterns of interlocking tiles. Written by Steve Sundstrom; 2004." +msgstr "" +"კვეთადი ფილების მოზაიკის ნიმუშები. დაწერილია სტივ სანდშტორმის მიერ. 2004." + +#: ../hacks/config/anemone.xml.h:1 +msgid "Anemone" +msgstr "ანემონი" + +#: ../hacks/config/anemone.xml.h:5 ../hacks/config/anemotaxis.xml.h:8 +#: ../hacks/config/beats.xml.h:5 ../hacks/config/binaryhorizon.xml.h:5 +#: ../hacks/config/binaryring.xml.h:8 ../hacks/config/blaster.xml.h:7 +#: ../hacks/config/bouboule.xml.h:5 ../hacks/config/boxed.xml.h:8 +#: ../hacks/config/cityflow.xml.h:5 ../hacks/config/coral.xml.h:11 +#: ../hacks/config/crackberg.xml.h:8 ../hacks/config/crumbler.xml.h:8 +#: ../hacks/config/cubenetic.xml.h:5 ../hacks/config/cubestorm.xml.h:8 +#: ../hacks/config/dangerball.xml.h:8 ../hacks/config/eruption.xml.h:5 +#: ../hacks/config/euler2d.xml.h:5 ../hacks/config/fiberlamp.xml.h:5 +#: ../hacks/config/flame.xml.h:8 ../hacks/config/flow.xml.h:5 +#: ../hacks/config/fluidballs.xml.h:5 ../hacks/config/fuzzyflakes.xml.h:8 +#: ../hacks/config/glcells.xml.h:8 ../hacks/config/glschool.xml.h:5 +#: ../hacks/config/goop.xml.h:8 ../hacks/config/grav.xml.h:5 +#: ../hacks/config/halftone.xml.h:5 ../hacks/config/halo.xml.h:5 +#: ../hacks/config/hydrostat.xml.h:14 ../hacks/config/interaggregate.xml.h:5 +#: ../hacks/config/interference.xml.h:11 ../hacks/config/jigsaw.xml.h:8 +#: ../hacks/config/julia.xml.h:5 ../hacks/config/kaleidescope.xml.h:5 +#: ../hacks/config/lisa.xml.h:5 ../hacks/config/lmorph.xml.h:5 +#: ../hacks/config/nerverot.xml.h:8 ../hacks/config/pedal.xml.h:5 +#: ../hacks/config/peepers.xml.h:8 ../hacks/config/petri.xml.h:10 +#: ../hacks/config/piecewise.xml.h:5 ../hacks/config/qix.xml.h:5 +#: ../hacks/config/rocks.xml.h:5 ../hacks/config/sierpinski.xml.h:5 +#: ../hacks/config/slip.xml.h:5 ../hacks/config/spiral.xml.h:5 +#: ../hacks/config/substrate.xml.h:8 ../hacks/config/swirl.xml.h:5 +#: ../hacks/config/thornbird.xml.h:5 ../hacks/config/topblock.xml.h:13 +#: ../hacks/config/unknownpleasures.xml.h:5 ../hacks/config/voronoi.xml.h:5 +#: ../hacks/config/whirlwindwarp.xml.h:2 ../hacks/config/wormhole.xml.h:8 +msgid "Few" +msgstr "რამდენიმე" + +#: ../hacks/config/anemone.xml.h:6 ../hacks/config/fuzzyflakes.xml.h:20 +#: ../hacks/config/hypnowheel.xml.h:13 +msgid "Arms" +msgstr "ხელები" + +#. +#. On a 2.93 gHz iMac i7, I get these rates with -delay 0: +#. +#. detail 3: invisible +#. detail 4: barely visible +#. detail 5: 1000+ fps, looks like noise at -delay 0, ok at -delay 20000 +#. detail 8: ~700+ fps +#. detail 9: ~400 fps +#. detail 10: ~300 fps +#. detail 11: ~100 fps +#. detail 12: ~50 fps +#. detail 13: ~17 fps +#. detail 14: ~8 fps +#. detail 15: ~2 fps +#. +#. With the default -delay, CPU load only starts causing the frame rate +#. to drop below 30 fps detail 12 or higher. +#. +#: ../hacks/config/anemone.xml.h:7 ../hacks/config/anemotaxis.xml.h:10 +#: ../hacks/config/ant.xml.h:13 ../hacks/config/apollonian.xml.h:9 +#: ../hacks/config/attraction.xml.h:19 ../hacks/config/beats.xml.h:7 +#: ../hacks/config/blaster.xml.h:9 ../hacks/config/bouboule.xml.h:7 +#: ../hacks/config/braid.xml.h:10 ../hacks/config/cityflow.xml.h:7 +#: ../hacks/config/coral.xml.h:13 ../hacks/config/critical.xml.h:7 +#: ../hacks/config/crumbler.xml.h:10 ../hacks/config/crystal.xml.h:7 +#: ../hacks/config/cubenetic.xml.h:7 ../hacks/config/cubestorm.xml.h:10 +#: ../hacks/config/cynosure.xml.h:7 ../hacks/config/deco.xml.h:7 +#: ../hacks/config/deluxe.xml.h:13 ../hacks/config/demon.xml.h:13 +#: ../hacks/config/discrete.xml.h:10 ../hacks/config/drift.xml.h:10 +#: ../hacks/config/epicycle.xml.h:7 ../hacks/config/eruption.xml.h:7 +#: ../hacks/config/euler2d.xml.h:7 ../hacks/config/fadeplot.xml.h:13 +#: ../hacks/config/fiberlamp.xml.h:7 ../hacks/config/flag.xml.h:11 +#: ../hacks/config/flame.xml.h:10 ../hacks/config/flow.xml.h:7 +#: ../hacks/config/fluidballs.xml.h:7 ../hacks/config/forest.xml.h:7 +#: ../hacks/config/fuzzyflakes.xml.h:10 ../hacks/config/galaxy.xml.h:11 +#: ../hacks/config/glcells.xml.h:10 ../hacks/config/goop.xml.h:10 +#: ../hacks/config/grav.xml.h:7 ../hacks/config/halftone.xml.h:7 +#: ../hacks/config/halo.xml.h:7 ../hacks/config/handsy.xml.h:10 +#: ../hacks/config/hopalong.xml.h:11 ../hacks/config/hydrostat.xml.h:10 +#: ../hacks/config/ifs.xml.h:64 ../hacks/config/imsmap.xml.h:13 +#: ../hacks/config/interaggregate.xml.h:7 ../hacks/config/interference.xml.h:13 +#: ../hacks/config/jigsaw.xml.h:10 ../hacks/config/julia.xml.h:13 +#: ../hacks/config/kaleidescope.xml.h:7 ../hacks/config/laser.xml.h:11 +#: ../hacks/config/lightning.xml.h:7 ../hacks/config/lisa.xml.h:7 +#: ../hacks/config/lissie.xml.h:10 ../hacks/config/lmorph.xml.h:7 +#: ../hacks/config/loop.xml.h:10 ../hacks/config/metaballs.xml.h:10 +#: ../hacks/config/mismunch.xml.h:10 ../hacks/config/moire.xml.h:7 +#: ../hacks/config/moire2.xml.h:7 ../hacks/config/mountain.xml.h:10 +#: ../hacks/config/munch.xml.h:10 ../hacks/config/nerverot.xml.h:10 +#: ../hacks/config/pedal.xml.h:7 ../hacks/config/peepers.xml.h:10 +#: ../hacks/config/penrose.xml.h:7 ../hacks/config/petri.xml.h:12 +#: ../hacks/config/piecewise.xml.h:7 ../hacks/config/polyominoes.xml.h:11 +#: ../hacks/config/qix.xml.h:7 ../hacks/config/razzledazzle.xml.h:10 +#: ../hacks/config/rocks.xml.h:7 ../hacks/config/rotor.xml.h:10 +#: ../hacks/config/shadebobs.xml.h:7 ../hacks/config/sierpinski.xml.h:7 +#: ../hacks/config/slip.xml.h:7 ../hacks/config/sphere.xml.h:7 +#: ../hacks/config/spiral.xml.h:7 ../hacks/config/squiral.xml.h:18 +#: ../hacks/config/starfish.xml.h:16 ../hacks/config/strange.xml.h:22 +#: ../hacks/config/swirl.xml.h:7 ../hacks/config/thornbird.xml.h:7 +#: ../hacks/config/topblock.xml.h:15 ../hacks/config/triangle.xml.h:7 +#: ../hacks/config/unknownpleasures.xml.h:7 ../hacks/config/vines.xml.h:7 +#: ../hacks/config/voronoi.xml.h:7 ../hacks/config/whirlwindwarp.xml.h:4 +#: ../hacks/config/worm.xml.h:7 +msgid "Many" +msgstr "ბევრი" + +#: ../hacks/config/anemone.xml.h:8 ../hacks/config/skytentacles.xml.h:3 +msgid "Tentacles" +msgstr "საცეცები" + +#: ../hacks/config/anemone.xml.h:9 ../hacks/config/cubestack.xml.h:8 +#: ../hacks/config/cubestorm.xml.h:14 ../hacks/config/cubetwist.xml.h:8 +#: ../hacks/config/deluxe.xml.h:5 ../hacks/config/fadeplot.xml.h:5 +#: ../hacks/config/fuzzyflakes.xml.h:21 ../hacks/config/glknots.xml.h:19 +#: ../hacks/config/hexstrut.xml.h:11 ../hacks/config/hilbert.xml.h:15 +#: ../hacks/config/hydrostat.xml.h:16 ../hacks/config/lmorph.xml.h:11 +#: ../hacks/config/razzledazzle.xml.h:14 ../hacks/config/skytentacles.xml.h:8 +#: ../hacks/config/starfish.xml.h:11 ../hacks/config/thornbird.xml.h:8 +msgid "Thin" +msgstr "თხელი" + +#: ../hacks/config/anemone.xml.h:10 ../hacks/config/cubestack.xml.h:9 +#: ../hacks/config/cubetwist.xml.h:9 ../hacks/config/fadeplot.xml.h:6 +#: ../hacks/config/fuzzyflakes.xml.h:22 ../hacks/config/glknots.xml.h:20 +#: ../hacks/config/hydrostat.xml.h:17 ../hacks/config/moire2.xml.h:8 +#: ../hacks/config/skytentacles.xml.h:9 ../hacks/config/thornbird.xml.h:9 +msgid "Thickness" +msgstr "სისქე" + +#: ../hacks/config/anemone.xml.h:11 ../hacks/config/cubestack.xml.h:10 +#: ../hacks/config/cubestorm.xml.h:16 ../hacks/config/cubetwist.xml.h:10 +#: ../hacks/config/deluxe.xml.h:7 ../hacks/config/fadeplot.xml.h:7 +#: ../hacks/config/fuzzyflakes.xml.h:23 ../hacks/config/glknots.xml.h:21 +#: ../hacks/config/hexstrut.xml.h:13 ../hacks/config/hilbert.xml.h:17 +#: ../hacks/config/hydrostat.xml.h:18 ../hacks/config/lmorph.xml.h:13 +#: ../hacks/config/razzledazzle.xml.h:16 ../hacks/config/skytentacles.xml.h:10 +#: ../hacks/config/starfish.xml.h:13 ../hacks/config/thornbird.xml.h:10 +msgid "Thick" +msgstr "სქელი" + +#: ../hacks/config/anemone.xml.h:12 ../hacks/config/pyro.xml.h:10 +#: ../hacks/config/splodesic.xml.h:7 ../hacks/config/winduprobot.xml.h:19 +msgid "Often" +msgstr "ხშირად" + +#: ../hacks/config/anemone.xml.h:13 +msgid "Withdraw freqency" +msgstr "გადახატვის სიხშირე" + +#: ../hacks/config/anemone.xml.h:14 +msgid "Rarely" +msgstr "იშვიათად" + +#: ../hacks/config/anemone.xml.h:15 +msgid "Turn speed" +msgstr "მობრუნების სიჩქარე" + +#: ../hacks/config/anemone.xml.h:17 +msgid "Wiggling tentacles. Written by Gabriel Finch; 2002." +msgstr "" + +#: ../hacks/config/anemotaxis.xml.h:1 +msgid "Anemotaxis" +msgstr "ანემოტაქსისი" + +#.