summaryrefslogtreecommitdiffstats
path: root/hacks/screenhack.c
diff options
context:
space:
mode:
Diffstat (limited to 'hacks/screenhack.c')
-rw-r--r--hacks/screenhack.c1013
1 files changed, 0 insertions, 1013 deletions
diff --git a/hacks/screenhack.c b/hacks/screenhack.c
deleted file mode 100644
index 14ec48b..0000000
--- a/hacks/screenhack.c
+++ /dev/null
@@ -1,1013 +0,0 @@
-/* xscreensaver, Copyright (c) 1992-2021 Jamie Zawinski <jwz@jwz.org>
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation. No representations are made about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *
- * And remember: X Windows is to graphics hacking as roman numerals are to
- * the square root of pi.
- */
-
-/* This file contains simple code to open a window or draw on the root.
- The idea being that, when writing a graphics hack, you can just link
- with this .o to get all of the uninteresting junk out of the way.
-
- Create a few static global procedures and variables:
-
- static void *YOURNAME_init (Display *, Window);
-
- Return an opaque structure representing your drawing state.
-
- static unsigned long YOURNAME_draw (Display *, Window, void *closure);
-
- Draw one frame.
- The `closure' arg is your drawing state, that you created in `init'.
- Return the number of microseconds to wait until the next frame.
-
- This should return in some small fraction of a second.
- Do not call `usleep' or loop excessively. For long loops, use a
- finite state machine.
-
- static void YOURNAME_reshape (Display *, Window, void *closure,
- unsigned int width, unsigned int height);
-
- Called when the size of the window changes with the new size.
-
- static Bool YOURNAME_event (Display *, Window, void *closure,
- XEvent *event);
-
- Called when a keyboard or mouse event arrives.
- Return True if you handle it in some way, False otherwise.
-
- static void YOURNAME_free (Display *, Window, void *closure);
-
- Called when you are done: free everything you've allocated,
- including your private `state' structure.
-
- NOTE: this is called in windowed-mode when the user typed
- 'q' or clicks on the window's close box; but when
- xscreensaver terminates this screenhack, it does so by
- killing the process with SIGSTOP. So this callback is
- mostly useless.
-
- static char YOURNAME_defaults [] = { "...", "...", ... , 0 };
-
- This variable is an array of strings, your default resources.
- Null-terminate the list.
-
- static XrmOptionDescRec YOURNAME_options[] = { { ... }, ... { 0,0,0,0 } }
-
- This variable describes your command-line options.
- Null-terminate the list.
-
- Finally , invoke the XSCREENSAVER_MODULE() macro to tie it all together.
-
- Additional caveats:
-
- - Make sure that all functions in your module are static (check this
- by running "nm -g" on the .o file).
-
- - Do not use global variables: all such info must be stored in the
- private `state' structure.
-
- - Do not use static function-local variables, either. Put it in `state'.
-
- Assume that there are N independent runs of this code going in the
- same address space at the same time: they must not affect each other.
-
- - Don't forget to write an XML file to describe the user interface
- of your screen saver module. See .../hacks/config/README for details.
- */
-
-#define DEBUG_PAIR
-
-#include <stdio.h>
-#include <X11/Intrinsic.h>
-#include <X11/IntrinsicP.h>
-#include <X11/CoreP.h>
-#include <X11/Shell.h>
-#include <X11/StringDefs.h>
-#include <X11/keysym.h>
-
-#ifdef __sgi
-# include <X11/SGIScheme.h> /* for SgiUseSchemes() */
-#endif /* __sgi */
-
-#include "screenhackI.h"
-#include "xmu.h"
-#include "version.h"
-#include "vroot.h"
-#include "fps.h"
-
-#ifdef HAVE_RECORD_ANIM
-# include "recanim.h"
-#endif
-
-#ifndef _XSCREENSAVER_VROOT_H_
-# error Error! You have an old version of vroot.h! Check -I args.
-#endif /* _XSCREENSAVER_VROOT_H_ */
-
-#ifndef isupper
-# define isupper(c) ((c) >= 'A' && (c) <= 'Z')
-#endif
-#ifndef _tolower
-# define _tolower(c) ((c) - 'A' + 'a')
-#endif
-
-
-/* This is defined by the SCREENHACK_MAIN() macro via screenhack.h.
- */
-extern struct xscreensaver_function_table *xscreensaver_function_table;
-
-
-const char *progname; /* used by hacks in error messages */
-const char *progclass; /* used by ../utils/resources.c */
-Bool mono_p; /* used by hacks */
-
-#ifdef EXIT_AFTER
-static time_t exit_after; /* Exit gracefully after N seconds */
-#endif
-
-static XrmOptionDescRec default_options [] = {
- { "-root", ".root", XrmoptionNoArg, "True" },
- { "-window", ".root", XrmoptionNoArg, "False" },
- { "-mono", ".mono", XrmoptionNoArg, "True" },
- { "-install", ".installColormap", XrmoptionNoArg, "True" },
- { "-noinstall",".installColormap", XrmoptionNoArg, "False" },
- { "-visual", ".visualID", XrmoptionSepArg, 0 },
- { "-window-id", ".windowID", XrmoptionSepArg, 0 },
- { "-fps", ".doFPS", XrmoptionNoArg, "True" },
- { "-no-fps", ".doFPS", XrmoptionNoArg, "False" },
-
-# ifdef DEBUG_PAIR
- { "-pair", ".pair", XrmoptionNoArg, "True" },
-# endif
-# ifdef HAVE_RECORD_ANIM
- { "-record-animation", ".recordAnim", XrmoptionSepArg, 0 },
-# endif
-# ifdef EXIT_AFTER
- { "-exit-after", ".exitAfter", XrmoptionSepArg, 0 },
-# endif
-
- { 0, 0, 0, 0 }
-};
-
-static char *default_defaults[] = {
- ".root: false",
- "*geometry: 1280x720", /* this should be .geometry, but noooo... */
- "*mono: false",
- "*installColormap: false",
- "*doFPS: false",
- "*multiSample: false",
- "*visualID: default",
- "*windowID: ",
- "*desktopGrabber: xscreensaver-getimage %s",
- 0
-};
-
-static XrmOptionDescRec *merged_options;
-static int merged_options_size;
-static char **merged_defaults;
-
-
-static void
-merge_options (void)
-{
- struct xscreensaver_function_table *ft = xscreensaver_function_table;
-
- const XrmOptionDescRec *options = ft->options;
- const char * const *defaults = ft->defaults;
- const char *progclass = ft->progclass;
-
- int def_opts_size, opts_size;
- int def_defaults_size, defaults_size;
-
- for (def_opts_size = 0; default_options[def_opts_size].option;
- def_opts_size++)
- ;
- for (opts_size = 0; options[opts_size].option; opts_size++)
- ;
-
- merged_options_size = def_opts_size + opts_size;
- merged_options = (XrmOptionDescRec *)
- malloc ((merged_options_size + 1) * sizeof(*default_options));
- memcpy (merged_options, default_options,
- (def_opts_size * sizeof(*default_options)));
- memcpy (merged_options + def_opts_size, options,
- ((opts_size + 1) * sizeof(*default_options)));
-
- for (def_defaults_size = 0; default_defaults[def_defaults_size];
- def_defaults_size++)
- ;
- for (defaults_size = 0; defaults[defaults_size]; defaults_size++)
- ;
- merged_defaults = (char **)
- malloc ((def_defaults_size + defaults_size + 1) * sizeof (*defaults));;
- memcpy (merged_defaults, default_defaults,
- def_defaults_size * sizeof(*defaults));
- memcpy (merged_defaults + def_defaults_size, defaults,
- (defaults_size + 1) * sizeof(*defaults));
-
- /* This totally sucks. Xt should behave like this by default.
- If the string in `defaults' looks like ".foo", change that
- to "Progclass.foo".
- */
- {
- char **s;
- for (s = merged_defaults; *s; s++)
- if (**s == '.')
- {
- const char *oldr = *s;
- char *newr = (char *) malloc(strlen(oldr) + strlen(progclass) + 3);
- strcpy (newr, progclass);
- strcat (newr, oldr);
- *s = newr;
- }
- else
- *s = strdup (*s);
- }
-}
-
-
-/* Make the X errors print out the name of this program, so we have some
- clue which one has a bug when they die under the screensaver.
- */
-
-static int
-screenhack_ehandler (Display *dpy, XErrorEvent *error)
-{
- fprintf (stderr, "\nX error in %s:\n", progname);
- if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
- exit (-1);
- else
- fprintf (stderr, " (nonfatal.)\n");
- return 0;
-}
-
-static Bool
-MapNotify_event_p (Display *dpy, XEvent *event, XPointer window)
-{
- return (event->xany.type == MapNotify &&
- event->xvisibility.window == (Window) window);
-}
-
-
-static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW, XA_NET_WM_PID;
-
-/* Dead-trivial event handling: exits if "q" or "ESC" are typed.
- Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received.
- Returns False if the screen saver should now terminate.
- */
-static Bool
-screenhack_handle_event_1 (Display *dpy, XEvent *event)
-{
- switch (event->xany.type)
- {
- case KeyPress:
- {
- KeySym keysym;
- char c = 0;
- XLookupString (&event->xkey, &c, 1, &keysym, 0);
- if (c == 'q' ||
- c == 'Q' ||
- c == 3 || /* ^C */
- c == 27) /* ESC */
- return False; /* exit */
- else if (! (keysym >= XK_Shift_L && keysym <= XK_Hyper_R))
- XBell (dpy, 0); /* beep for non-chord keys */
- }
- break;
- case ButtonPress:
- XBell (dpy, 0);
- break;
- case ClientMessage:
- {
- if (event->xclient.message_type != XA_WM_PROTOCOLS)
- {
- char *s = XGetAtomName(dpy, event->xclient.message_type);
- if (!s) s = "(null)";
- fprintf (stderr, "%s: unknown ClientMessage %s received!\n",
- progname, s);
- }
- else if (event->xclient.data.l[0] != XA_WM_DELETE_WINDOW)
- {
- char *s1 = XGetAtomName(dpy, event->xclient.message_type);
- char *s2 = XGetAtomName(dpy, event->xclient.data.l[0]);
- if (!s1) s1 = "(null)";
- if (!s2) s2 = "(null)";
- fprintf (stderr, "%s: unknown ClientMessage %s[%s] received!\n",
- progname, s1, s2);
- }
- else
- {
- return False; /* exit */
- }
- }
- break;
- }
- return True;
-}
-
-
-static Visual *
-pick_visual (Screen *screen)
-{
- struct xscreensaver_function_table *ft = xscreensaver_function_table;
-
- if (ft->pick_visual_hook)
- {
- Visual *v = ft->pick_visual_hook (screen);
- if (v) return v;
- }
-
- return get_visual_resource (screen, "visualID", "VisualID", False);
-}
-
-
-/* Notice when the user has requested a different visual or colormap
- on a pre-existing window (e.g., "-root -visual truecolor" or
- "-window-id 0x2c00001 -install") and complain, since when drawing
- on an existing window, we have no choice about these things.
- */
-static void
-visual_warning (Screen *screen, Window window, Visual *visual, Colormap cmap,
- Bool window_p)
-{
- struct xscreensaver_function_table *ft = xscreensaver_function_table;
-
- char *visual_string = get_string_resource (DisplayOfScreen (screen),
- "visualID", "VisualID");
- Visual *desired_visual = pick_visual (screen);
- char win[100];
- char why[100];
-
- if (window == RootWindowOfScreen (screen))
- strcpy (win, "root window");
- else
- sprintf (win, "window 0x%lx", (unsigned long) window);
-
- if (window_p)
- sprintf (why, "-window-id 0x%lx", (unsigned long) window);
- else
- strcpy (why, "-root");
-
- if (visual_string && *visual_string)
- {
- char *s;
- for (s = visual_string; *s; s++)
- if (isupper (*s)) *s = _tolower (*s);
-
- if (!strcmp (visual_string, "default") ||
- !strcmp (visual_string, "default") ||
- !strcmp (visual_string, "best"))
- /* don't warn about these, just silently DWIM. */
- ;
- else if (visual != desired_visual)
- {
- fprintf (stderr, "%s: ignoring `-visual %s' because of `%s'.\n",
- progname, visual_string, why);
- fprintf (stderr, "%s: using %s's visual 0x%lx.\n",
- progname, win, XVisualIDFromVisual (visual));
- }
- free (visual_string);
- }
-
- if (visual == DefaultVisualOfScreen (screen) &&
- has_writable_cells (screen, visual) &&
- get_boolean_resource (DisplayOfScreen (screen),
- "installColormap", "InstallColormap"))
- {
- fprintf (stderr, "%s: ignoring `-install' because of `%s'.\n",
- progname, why);
- fprintf (stderr, "%s: using %s's colormap 0x%lx.\n",
- progname, win, (unsigned long) cmap);
- }
-
- if (ft->validate_visual_hook)
- {
- if (! ft->validate_visual_hook (screen, win, visual))
- exit (1);
- }
-}
-
-
-static void
-fix_fds (void)
-{
- /* Bad Things Happen if stdin, stdout, and stderr have been closed
- (as by the `sh incantation "attraction >&- 2>&-"). When you do
- that, the X connection gets allocated to one of these fds, and
- then some random library writes to stderr, and random bits get
- stuffed down the X pipe, causing "Xlib: sequence lost" errors.
- So, we cause the first three file descriptors to be open to
- /dev/null if they aren't open to something else already. This
- must be done before any other files are opened (or the closing
- of that other file will again free up one of the "magic" first
- three FDs.)
-
- We do this by opening /dev/null three times, and then closing
- those fds, *unless* any of them got allocated as #0, #1, or #2,
- in which case we leave them open. Gag.
-
- Really, this crap is technically required of *every* X program,
- if you want it to be robust in the face of "2>&-".
- */
- int fd0 = open ("/dev/null", O_RDWR);
- int fd1 = open ("/dev/null", O_RDWR);
- int fd2 = open ("/dev/null", O_RDWR);
- if (fd0 > 2) close (fd0);
- if (fd1 > 2) close (fd1);
- if (fd2 > 2) close (fd2);
-}
-
-
-static Boolean
-screenhack_table_handle_events (Display *dpy,
- const struct xscreensaver_function_table *ft,
- Window window, void *closure
-#ifdef DEBUG_PAIR
- , Window window2, void *closure2
-#endif
- )
-{
- XtAppContext app = XtDisplayToApplicationContext (dpy);
- XtInputMask m = XtAppPending (app);
-
- /* Process non-X11 Xt events (timers, files, signals) without blocking. */
- if (m & ~XtIMXEvent)
- XtAppProcessEvent (app, ~XtIMXEvent);
-
- /* Process all pending X11 events without blocking. */
- while (XPending (dpy))
- {
- XEvent event;
- XNextEvent (dpy, &event);
-
- if (event.xany.type == ConfigureNotify)
- {
- if (event.xany.window == window)
- ft->reshape_cb (dpy, window, closure,
- event.xconfigure.width, event.xconfigure.height);
-#ifdef DEBUG_PAIR
- if (window2 && event.xany.window == window2)
- ft->reshape_cb (dpy, window2, closure2,
- event.xconfigure.width, event.xconfigure.height);
-#endif
- }
- else if (event.xany.type == ClientMessage ||
- (! (event.xany.window == window
- ? ft->event_cb (dpy, window, closure, &event)
-#ifdef DEBUG_PAIR
- : (window2 && event.xany.window == window2)
- ? ft->event_cb (dpy, window2, closure2, &event)
-#endif
- : 0)))
- if (! screenhack_handle_event_1 (dpy, &event))
- return False;
-
- /* Last chance to process Xt timers before blocking. */
- m = XtAppPending (app);
- if (m & ~XtIMXEvent)
- XtAppProcessEvent (app, ~XtIMXEvent);
- }
-
-# ifdef EXIT_AFTER
- if (exit_after != 0 && time ((time_t *) 0) >= exit_after)
- return False;
-# endif
-
- return True;
-}
-
-
-static Boolean
-usleep_and_process_events (Display *dpy,
- const struct xscreensaver_function_table *ft,
- Window window, fps_state *fpst, void *closure,
- unsigned long delay
-#ifdef DEBUG_PAIR
- , Window window2, fps_state *fpst2, void *closure2,
- unsigned long delay2
-#endif
-# ifdef HAVE_RECORD_ANIM
- , record_anim_state *anim_state
-# endif
- )
-{
- do {
- unsigned long quantum = 33333; /* 30 fps */
- if (quantum > delay)
- quantum = delay;
- delay -= quantum;
-
- XSync (dpy, False);
-
-#ifdef HAVE_RECORD_ANIM
- if (anim_state) screenhack_record_anim (anim_state);
-#endif
-
- if (quantum > 0)
- {
- usleep (quantum);
- if (fpst) fps_slept (fpst, quantum);
-#ifdef DEBUG_PAIR
- if (fpst2) fps_slept (fpst2, quantum);
-#endif
- }
-
- if (! screenhack_table_handle_events (dpy, ft, window, closure
-#ifdef DEBUG_PAIR
- , window2, closure2
-#endif
- ))
- return False;
- } while (delay > 0);
-
- return True;
-}
-
-
-static void
-screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure)
-{
- fps_compute (fpst, 0, -1);
- fps_draw (fpst);
-}
-
-
-static void
-run_screenhack_table (Display *dpy,
- Window window,
-# ifdef DEBUG_PAIR
- Window window2,
-# endif
-# ifdef HAVE_RECORD_ANIM
- record_anim_state *anim_state,
-# endif
- const struct xscreensaver_function_table *ft)
-{
-
- /* Kludge: even though the init_cb functions are declared to take 2 args,
- actually call them with 3, for the benefit of xlockmore_init() and
- xlockmore_setup().
- */
- void *(*init_cb) (Display *, Window, void *) =
- (void *(*) (Display *, Window, void *)) ft->init_cb;
-
- void (*fps_cb) (Display *, Window, fps_state *, void *) = ft->fps_cb;
-
- void *closure = init_cb (dpy, window, ft->setup_arg);
- fps_state *fpst = fps_init (dpy, window);
- unsigned long delay = 0;
-
-#ifdef DEBUG_PAIR
- void *closure2 = 0;
- fps_state *fpst2 = 0;
- unsigned long delay2 = 0;
- if (window2) closure2 = init_cb (dpy, window2, ft->setup_arg);
- if (window2) fpst2 = fps_init (dpy, window2);
-#endif
-
- if (! closure) /* if it returns nothing, it can't possibly be re-entrant. */
- abort();
-
- if (! fps_cb) fps_cb = screenhack_do_fps;
-
- while (1)
- {
- if (! usleep_and_process_events (dpy, ft,
- window, fpst, closure, delay
-#ifdef DEBUG_PAIR
- , window2, fpst2, closure2, delay2
-#endif
-#ifdef HAVE_RECORD_ANIM
- , anim_state
-#endif
- ))
- break;
-
- delay = ft->draw_cb (dpy, window, closure);
-#ifdef DEBUG_PAIR
- delay2 = 0;
- if (window2) delay2 = ft->draw_cb (dpy, window2, closure2);
-#endif
-
- if (fpst) fps_cb (dpy, window, fpst, closure);
-#ifdef DEBUG_PAIR
- if (fpst2) fps_cb (dpy, window2, fpst2, closure2);
-#endif
- }
-
-#ifdef HAVE_RECORD_ANIM
- /* Exiting before target frames hit: write the video anyway. */
- if (anim_state) screenhack_record_anim_free (anim_state);
-#endif
-
- if (fpst) ft->fps_free (fpst);
-#ifdef DEBUG_PAIR
- if (fpst2) ft->fps_free (fpst2);
-#endif
-
- ft->free_cb (dpy, window, closure);
-#ifdef DEBUG_PAIR
- if (window2) ft->free_cb (dpy, window2, closure2);
-#endif
-}
-
-
-static Widget
-make_shell (Screen *screen, Widget toplevel, int width, int height)
-{
- Display *dpy = DisplayOfScreen (screen);
- Visual *visual = pick_visual (screen);
- Boolean def_visual_p = (toplevel &&
- visual == DefaultVisualOfScreen (screen));
-
- if (width <= 0) width = 600;
- if (height <= 0) height = 480;
-
- if (def_visual_p)
- {
- Window window;
- XtVaSetValues (toplevel,
- XtNmappedWhenManaged, False,
- XtNwidth, width,
- XtNheight, height,
- XtNinput, True, /* for WM_HINTS */
- NULL);
- XtRealizeWidget (toplevel);
- window = XtWindow (toplevel);
-
- if (get_boolean_resource (dpy, "installColormap", "InstallColormap"))
- {
- Colormap cmap =
- XCreateColormap (dpy, window, DefaultVisualOfScreen (screen),
- AllocNone);
- XSetWindowColormap (dpy, window, cmap);
- }
- }
- else
- {
- unsigned int bg, bd;
- Widget new;
- Colormap cmap = XCreateColormap (dpy, VirtualRootWindowOfScreen(screen),
- visual, AllocNone);
- bg = get_pixel_resource (dpy, cmap, "background", "Background");
- bd = get_pixel_resource (dpy, cmap, "borderColor", "Foreground");
-
- new = XtVaAppCreateShell (progname, progclass,
- topLevelShellWidgetClass, dpy,
- XtNmappedWhenManaged, False,
- XtNvisual, visual,
- XtNdepth, visual_depth (screen, visual),
- XtNwidth, width,
- XtNheight, height,
- XtNcolormap, cmap,
- XtNbackground, (Pixel) bg,
- XtNborderColor, (Pixel) bd,
- XtNinput, True, /* for WM_HINTS */
- NULL);
-
- if (!toplevel) /* kludge for the second window in -pair mode... */
- XtVaSetValues (new, XtNx, 0, XtNy, 550, NULL);
-
- XtRealizeWidget (new);
- toplevel = new;
- }
-
- return toplevel;
-}
-
-static void
-init_window (Display *dpy, Widget toplevel, const char *title)
-{
- Window window;
- XWindowAttributes xgwa;
- long pid = getpid();
- XtPopup (toplevel, XtGrabNone);
- XtVaSetValues (toplevel, XtNtitle, title, NULL);
-
- /* Select KeyPress, and announce that we accept WM_DELETE_WINDOW.
- */
- window = XtWindow (toplevel);
- XGetWindowAttributes (dpy, window, &xgwa);
- XSelectInput (dpy, window,
- (xgwa.your_event_mask | KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask));
- XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32,
- PropModeReplace,
- (unsigned char *) &XA_WM_DELETE_WINDOW, 1);
- XChangeProperty (dpy, window, XA_NET_WM_PID, XA_CARDINAL, 32,
- PropModeReplace, (unsigned char *)&pid, 1);
-}
-
-
-int
-main (int argc, char **argv)
-{
- struct xscreensaver_function_table *ft = xscreensaver_function_table;
-
- XWindowAttributes xgwa;
- Widget toplevel;
- Display *dpy;
- Window window;
-# ifdef DEBUG_PAIR
- Window window2 = 0;
- Widget toplevel2 = 0;
-# endif
-# ifdef HAVE_RECORD_ANIM
- record_anim_state *anim_state = 0;
-# endif
- XtAppContext app;
- Bool root_p;
- Window on_window = 0;
- XEvent event;
- Boolean dont_clear;
- char version[255];
-
- fix_fds();
-
- progname = argv[0]; /* reset later */
- progclass = ft->progclass;
-
- if (ft->setup_cb)
- ft->setup_cb (ft, ft->setup_arg);
-
- merge_options ();
-
-#ifdef __sgi
- /* We have to do this on SGI to prevent the background color from being
- overridden by the current desktop color scheme (we'd like our backgrounds
- to be black, thanks.) This should be the same as setting the
- "*useSchemes: none" resource, but it's not -- if that resource is
- present in the `default_defaults' above, it doesn't work, though it
- does work when passed as an -xrm arg on the command line. So screw it,
- turn them off from C instead.
- */
- SgiUseSchemes ("none");
-#endif /* __sgi */
-
- /* Xt and xscreensaver predate the "--arg" convention, so convert
- double dashes to single. */
- {
- int i;
- for (i = 1; i < argc; i++)
- if (argv[i][0] == '-' && argv[i][1] == '-')
- argv[i]++;
- }
-
- toplevel = XtAppInitialize (&app, progclass, merged_options,
- merged_options_size, &argc, argv,
- merged_defaults, 0, 0);
-
- dpy = XtDisplay (toplevel);
-
- XtGetApplicationNameAndClass (dpy,
- (char **) &progname,
- (char **) &progclass);
-
- /* half-assed way of avoiding buffer-overrun attacks. */
- if (strlen (progname) >= 100) ((char *) progname)[100] = 0;
-
- XSetErrorHandler (screenhack_ehandler);
-
- XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);
- XA_WM_DELETE_WINDOW = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
- XA_NET_WM_PID = XInternAtom (dpy, "_NET_WM_PID", False);
-
- {
- char *v = (char *) strdup(strchr(screensaver_id, ' '));
- char *s1, *s2, *s3, *s4;
- const char *ot = get_string_resource (dpy, "title", "Title");
- s1 = (char *) strchr(v, ' '); s1++;
- s2 = (char *) strchr(s1, ' ');
- s3 = (char *) strchr(v, '('); s3++;
- s4 = (char *) strchr(s3, ')');
- *s2 = 0;
- *s4 = 0;
- if (ot && !*ot) ot = 0;
- sprintf (version, "%.50s%s%s: from the XScreenSaver %s distribution (%s)",
- (ot ? ot : ""),
- (ot ? ": " : ""),
- progclass, s1, s3);
- free(v);
- }
-
- if (argc > 1)
- {
- int i;
- int x = 18;
- int end = 78;
- Bool help_p = (!strcmp(argv[1], "-help") ||
- !strcmp(argv[1], "--help"));
- fprintf (stderr, "%s\n", version);
- fprintf (stderr, "\n\thttps://www.jwz.org/xscreensaver/\n\n");
-
- if (!help_p)
- fprintf(stderr, "Unrecognised option: %s\n", argv[1]);
- fprintf (stderr, "Options include: ");
- for (i = 0; i < merged_options_size; i++)
- {
- char *sw = merged_options [i].option;
- Bool argp = (merged_options [i].argKind == XrmoptionSepArg);
- int size = strlen (sw) + (argp ? 6 : 0) + 2;
- if (x + size >= end)
- {
- fprintf (stderr, "\n\t\t ");
- x = 18;
- }
- x += size;
- fprintf (stderr, "%s", sw);
- if (argp) fprintf (stderr, " <arg>");
- if (i != merged_options_size - 1) fprintf (stderr, ", ");
- }
-
- fprintf (stderr, ".\n");
-
-#if 0
- if (help_p)
- {
- fprintf (stderr, "\nResources:\n\n");
- for (i = 0; i < merged_options_size; i++)
- {
- const char *opt = merged_options [i].option;
- const char *res = merged_options [i].specifier + 1;
- const char *val = merged_options [i].value;
- char *s = get_string_resource (dpy, (char *) res, (char *) res);
-
- if (s)
- {
- int L = strlen(s);
- while (L > 0 && (s[L-1] == ' ' || s[L-1] == '\t'))
- s[--L] = 0;
- }
-
- fprintf (stderr, " %-16s %-18s ", opt, res);
- if (merged_options [i].argKind == XrmoptionSepArg)
- {
- fprintf (stderr, "[%s]", (s ? s : "?"));
- }
- else
- {
- fprintf (stderr, "%s", (val ? val : "(null)"));
- if (val && s && !strcasecmp (val, s))
- fprintf (stderr, " [default]");
- }
- fprintf (stderr, "\n");
- }
- fprintf (stderr, "\n");
- }
-#endif
-
- exit (help_p ? 0 : 1);
- }
-
- {
- char **s;
- for (s = merged_defaults; *s; s++)
- free(*s);
- }
-
- free (merged_options);
- free (merged_defaults);
- merged_options = 0;
- merged_defaults = 0;
-
- dont_clear = get_boolean_resource (dpy, "dontClearRoot", "Boolean");
- mono_p = get_boolean_resource (dpy, "mono", "Boolean");
- if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
- mono_p = True;
-
- root_p = get_boolean_resource (dpy, "root", "Boolean");
-
-# ifdef EXIT_AFTER
- {
- int secs = get_integer_resource (dpy, "exitAfter", "Integer");
- exit_after = (secs > 0
- ? time((time_t *) 0) + secs
- : 0);
- }
-# endif
-
- {
- char *s = get_string_resource (dpy, "windowID", "WindowID");
- if (s && *s)
- on_window = get_integer_resource (dpy, "windowID", "WindowID");
- if (s) free (s);
- }
-
- if (on_window)
- {
- window = (Window) on_window;
- XtDestroyWidget (toplevel);
- XGetWindowAttributes (dpy, window, &xgwa);
- visual_warning (xgwa.screen, window, xgwa.visual, xgwa.colormap, True);
-
- /* Select KeyPress and resize events on the external window.
- */
- xgwa.your_event_mask |= KeyPressMask | StructureNotifyMask;
- XSelectInput (dpy, window, xgwa.your_event_mask);
-
- /* Select ButtonPress and ButtonRelease events on the external window,
- if no other app has already selected them (only one app can select
- ButtonPress at a time: BadAccess results.)
- */
- if (! (xgwa.all_event_masks & (ButtonPressMask | ButtonReleaseMask)))
- XSelectInput (dpy, window,
- (xgwa.your_event_mask |
- ButtonPressMask | ButtonReleaseMask));
- }
- else if (root_p)
- {
- window = VirtualRootWindowOfScreen (XtScreen (toplevel));
- XtDestroyWidget (toplevel);
- XGetWindowAttributes (dpy, window, &xgwa);
- /* With RANDR, the root window can resize! */
- XSelectInput (dpy, window, xgwa.your_event_mask | StructureNotifyMask);
- visual_warning (xgwa.screen, window, xgwa.visual, xgwa.colormap, False);
- }
- else
- {
- Widget new = make_shell (XtScreen (toplevel), toplevel,
- toplevel->core.width,
- toplevel->core.height);
- if (new != toplevel)
- {
- XtDestroyWidget (toplevel);
- toplevel = new;
- }
-
- init_window (dpy, toplevel, version);
- window = XtWindow (toplevel);
- XGetWindowAttributes (dpy, window, &xgwa);
-
-# ifdef DEBUG_PAIR
- if (get_boolean_resource (dpy, "pair", "Boolean"))
- {
- toplevel2 = make_shell (xgwa.screen, 0,
- toplevel->core.width,
- toplevel->core.height);
- init_window (dpy, toplevel2, version);
- window2 = XtWindow (toplevel2);
- }
-# endif /* DEBUG_PAIR */
- }
-
- if (!dont_clear)
- {
- unsigned int bg = get_pixel_resource (dpy, xgwa.colormap,
- "background", "Background");
- XSetWindowBackground (dpy, window, bg);
- XClearWindow (dpy, window);
-# ifdef DEBUG_PAIR
- if (window2)
- {
- XSetWindowBackground (dpy, window2, bg);
- XClearWindow (dpy, window2);
- }
-# endif
- }
-
- if (!root_p && !on_window)
- /* wait for it to be mapped */
- XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
-
- XSync (dpy, False);
-
- /* This is the one and only place that the random-number generator is
- seeded in any screenhack. You do not need to seed the RNG again,
- it is done for you before your code is invoked. */
-# undef ya_rand_init
- ya_rand_init (0);
-
-
-#ifdef HAVE_RECORD_ANIM
- {
- int frames = get_integer_resource (dpy, "recordAnim", "Integer");
- if (frames > 0)
- anim_state = screenhack_record_anim_init (xgwa.screen, window, frames);
- }
-#endif
-
- run_screenhack_table (dpy, window,
-# ifdef DEBUG_PAIR
- window2,
-# endif
-# ifdef HAVE_RECORD_ANIM
- anim_state,
-# endif
- ft);
-
-#ifdef HAVE_RECORD_ANIM
- if (anim_state) screenhack_record_anim_free (anim_state);
-#endif
-
- XtDestroyWidget (toplevel);
- XtDestroyApplicationContext (app);
-
- return 0;
-}