ftp://ftp.ntnu.no/old/pub/X11/R5contrib/xscreensaver-1.17.tar.gz
[xscreensaver] / hacks / screenhack.c
1 /* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  *
11  * And remember: X Windows is to graphics hacking as roman numerals are to
12  * the square root of pi.
13  */
14
15 /* This file contains simple code to open a window or draw on the root.
16    The idea being that, when writing a graphics hack, you can just link
17    with this .o to get all of the uninteresting junk out of the way.
18
19    -  create a procedure `screenhack(dpy, window)'
20
21    -  create a variable `char *progclass' which names this program's
22       resource class.
23
24    -  create a variable `char defaults []' for the default resources.
25
26    -  create a variable `XrmOptionDescRec options []' for the command-line,
27       and `int options_size' which is `XtNumber (options)'.
28
29    And that's it...
30  */
31
32 #include "version.h"
33
34 #include <stdio.h>
35 #include <X11/Intrinsic.h>
36 #include <X11/IntrinsicP.h>
37 #include <X11/CoreP.h>
38 #include <X11/Xmu/Error.h>
39 #include "screenhack.h"
40
41 char *progname;
42 XrmDatabase db;
43 Bool mono_p;
44
45
46 static XrmOptionDescRec default_options [] = {
47   { "-root",    ".root",                XrmoptionNoArg, "True" },
48   { "-window",  ".root",                XrmoptionNoArg, "False" },
49   { "-mono",    ".mono",                XrmoptionNoArg, "True" },
50   { "-install", ".installColormap",     XrmoptionNoArg, "True" }
51 };
52
53 static char *default_defaults[] = {
54   "*root:               false",
55   "*geometry:           500x500", /* this should be .geometry, but nooooo... */
56   "*mono:               false",
57   "*installColormap:    false",
58   0
59 };
60
61 static XrmOptionDescRec *merged_options;
62 static int merged_options_size;
63 static char **merged_defaults;
64
65 static void
66 merge_options ()
67 {
68   int options_sizeof = options_size * sizeof (options[0]);
69   int defaults_size;
70   merged_options_size = XtNumber (default_options) + options_size;
71   merged_options = (XrmOptionDescRec *)
72     malloc (sizeof (default_options) + options_sizeof);
73   bcopy (options, merged_options, options_sizeof);
74   bcopy (default_options, merged_options + options_size,
75          sizeof (default_options));
76
77   for (defaults_size = 0; defaults [defaults_size]; defaults_size++);
78   merged_defaults = (char **)
79     malloc (sizeof (default_defaults) + (defaults_size * sizeof (char *)));
80   bcopy (default_defaults, merged_defaults, sizeof (default_defaults));
81   bcopy (defaults, merged_defaults - 1 +
82          (sizeof (default_defaults) / sizeof (default_defaults[0])),
83          ((defaults_size + 1) * sizeof (defaults[0])));
84 }
85
86 \f
87 /* Make the X errors print out the name of this program, so we have some
88    clue which one has a bug when they die under the screensaver.
89  */
90
91 static int
92 screenhack_ehandler (dpy, error)
93      Display *dpy;
94      XErrorEvent *error;
95 {
96   fprintf (stderr, "\nX error in %s:\n", progname);
97   if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
98     exit (-1);
99   else
100     fprintf (stderr, " (nonfatal.)\n");
101   return 0;
102 }
103
104 static Bool
105 MapNotify_event_p (dpy, event, window)
106      Display *dpy;
107      XEvent *event;
108      XPointer window;
109 {
110   return (event->xany.type == MapNotify &&
111           event->xvisibility.window == (Window) window);
112 }
113
114
115 void
116 main (argc, argv)
117      int argc;
118      char **argv;
119 {
120   XtAppContext app;
121   Widget toplevel;
122   Display *dpy;
123   Window window;
124   Colormap cmap;
125   Bool root_p;
126   XEvent event;
127
128   merge_options ();
129   toplevel = XtAppInitialize (&app, progclass, merged_options,
130                               merged_options_size, &argc, argv,
131                               merged_defaults, 0, 0);
132   dpy = XtDisplay (toplevel);
133   db = XtDatabase (dpy);
134   XtGetApplicationNameAndClass (dpy, &progname, &progclass);
135   XSetErrorHandler (screenhack_ehandler);
136   if (argc > 1)
137     {
138       int i;
139       int x = 18;
140       int end = 78;
141       fprintf (stderr, "%s: unrecognised option \"%s\"\n", progname, argv[1]);
142       fprintf (stderr, "Options include: ");
143       for (i = 0; i < merged_options_size; i++)
144         {
145           char *sw = merged_options [i].option;
146           Bool argp = (merged_options [i].argKind == XrmoptionSepArg);
147           int size = strlen (sw) + (argp ? 6 : 0) + 2;
148           if (x + size >= end)
149             {
150               fprintf (stderr, "\n\t\t ");
151               x = 18;
152             }
153           x += size;
154           fprintf (stderr, "%s", sw);
155           if (argp) fprintf (stderr, " <arg>");
156           if (i != merged_options_size - 1) fprintf (stderr, ", ");
157         }
158       fprintf (stderr, ".\n");
159       exit (1);
160     }
161
162   mono_p = get_boolean_resource ("mono", "Boolean");
163   if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
164     mono_p = True;
165
166   root_p = get_boolean_resource ("root", "Boolean");
167   if (root_p)
168     {
169       XWindowAttributes xgwa;
170       window = RootWindowOfScreen (XtScreen (toplevel));
171       XtDestroyWidget (toplevel);
172       XGetWindowAttributes (dpy, window, &xgwa);
173       cmap = xgwa.colormap;
174     }
175   else
176     {
177       XtRealizeWidget (toplevel);
178       window = XtWindow (toplevel);
179       if (get_boolean_resource ("installColormap", "InstallColormap"))
180         {
181           cmap = XCreateColormap (dpy, window,
182                                   DefaultVisualOfScreen (XtScreen (toplevel)),
183                                   AllocNone);
184           XSetWindowColormap (dpy, window, cmap);
185         }
186       else
187         cmap = DefaultColormap (dpy, DefaultScreen (dpy));
188     }
189   if (!get_boolean_resource ("dontClearWindow", "Boolean")) /* kludge-o-rama */
190     {
191       XSetWindowBackground (dpy, window,
192                             get_pixel_resource ("background", "Background",
193                                                 dpy, cmap));
194       XClearWindow (dpy, window);
195     }
196
197   if (!root_p && toplevel->core.mapped_when_managed)
198     /* wait for it to be mapped */
199     XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
200
201   XSync (dpy, False);
202   srandom ((int) time ((time_t *) 0));
203   screenhack (dpy, window);
204 }