2e45e6d82bdfbd95dbe5db9dfb94091d433347cf
[xscreensaver] / hacks / bsod.c
1 /* xscreensaver, Copyright (c) 1998, 2000 Jamie Zawinski <jwz@jwz.org>
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  * Blue Screen of Death: the finest in personal computer emulation.
12  * Concept cribbed from Stephen Martin <smartin@mks.com>;
13  * this version written by jwz, 4-Jun-98.
14  *
15  *   TODO:
16  *      -  Should simulate a Unix kernel panic and reboot.
17  *      -  Making various boot noises would be fun, too.
18  *      -  Maybe scatter some random bits across the screen,
19  *         to simulate corruption of video ram?
20  *      -  Should randomize the various hex numbers printed.
21  */
22
23 #include "screenhack.h"
24 #include <stdio.h>
25 #include <X11/Xutil.h>
26
27 #ifdef HAVE_XPM
28 # include <X11/xpm.h>
29 # include "images/amiga.xpm"
30 #endif
31
32 #include "images/atari.xbm"
33 #include "images/mac.xbm"
34
35
36 static void
37 draw_string (Display *dpy, Window window, GC gc, XGCValues *gcv,
38              XFontStruct *font,
39              int xoff, int yoff,
40              int win_width, int win_height,
41              const char *string, int delay)
42 {
43   int x, y;
44   int width = 0, height = 0, cw = 0;
45   int char_width, line_height;
46
47   const char *s = string;
48   const char *se = string;
49
50   /* This pretty much assumes fixed-width fonts */
51   char_width = (font->per_char
52                 ? font->per_char['n'-font->min_char_or_byte2].width
53                 : font->min_bounds.width);
54   line_height = font->ascent + font->descent + 1;
55
56   while (1)
57     {
58       if (*s == '\n' || !*s)
59         {
60           height++;
61           if (cw > width) width = cw;
62           cw = 0;
63           if (!*s) break;
64         }
65       else
66         cw++;
67       s++;
68     }
69
70   x = (win_width - (width * char_width)) / 2;
71   y = (win_height - (height * line_height)) / 2;
72
73   if (x < 0) x = 2;
74   if (y < 0) y = 2;
75
76   x += xoff;
77   y += yoff;
78
79   se = s = string;
80   while (1)
81     {
82       if (*s == '\n' || !*s)
83         {
84           int off = 0;
85           Bool flip = False;
86
87           if (*se == '@' || *se == '_')
88             {
89               if (*se == '@') flip = True;
90               se++;
91               off = (char_width * (width - (s - se))) / 2;
92             }
93
94           if (flip)
95             {
96               XSetForeground(dpy, gc, gcv->background);
97               XSetBackground(dpy, gc, gcv->foreground);
98             }
99
100           if (s != se)
101             XDrawImageString(dpy, window, gc, x+off, y+font->ascent, se, s-se);
102
103           if (flip)
104             {
105               XSetForeground(dpy, gc, gcv->foreground);
106               XSetBackground(dpy, gc, gcv->background);
107             }
108
109           se = s;
110           y += line_height;
111           if (!*s) break;
112           se = s+1;
113
114           if (delay)
115             {
116               XSync(dpy, False);
117               usleep(delay);
118             }
119         }
120       s++;
121     }
122 }
123
124
125 static Pixmap
126 double_pixmap(Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
127              int pix_w, int pix_h)
128 {
129   int x, y;
130   Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
131   XImage *i1 = XGetImage(dpy, pixmap, 0, 0, pix_w, pix_h, ~0L, ZPixmap);
132   XImage *i2 = XCreateImage(dpy, visual, depth, ZPixmap, 0, 0,
133                             pix_w*2, pix_h*2, 8, 0);
134   i2->data = (char *) calloc(i2->height, i2->bytes_per_line);
135   for (y = 0; y < pix_h; y++)
136     for (x = 0; x < pix_w; x++)
137       {
138         unsigned long p = XGetPixel(i1, x, y);
139         XPutPixel(i2, x*2,   y*2,   p);
140         XPutPixel(i2, x*2+1, y*2,   p);
141         XPutPixel(i2, x*2,   y*2+1, p);
142         XPutPixel(i2, x*2+1, y*2+1, p);
143       }
144   free(i1->data); i1->data = 0;
145   XDestroyImage(i1);
146   XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
147   free(i2->data); i2->data = 0;
148   XDestroyImage(i2);
149   XFreePixmap(dpy, pixmap);
150   return p2;
151 }
152
153
154 /* Sleep for N seconds and return False.  But if a key or mouse event is
155    seen, discard all pending key or mouse events, and return True.
156  */
157 static Bool
158 bsod_sleep(Display *dpy, int seconds)
159 {
160   int q = seconds * 4;
161   int quantum = 250000;
162
163   if (seconds == -1)
164     q = 1, quantum = 100000;
165
166   do
167     {
168       XSync(dpy, False);
169       while (XPending (dpy))
170         {
171           XEvent event;
172           XNextEvent (dpy, &event);
173           if (event.xany.type == ButtonPress)
174             return True;
175           if (event.xany.type == KeyPress)
176             {
177               KeySym keysym;
178               char c = 0;
179               XLookupString (&event.xkey, &c, 1, &keysym, 0);
180               if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
181                 return True;
182             }
183           screenhack_handle_event (dpy, &event);
184         }
185
186       if (q > 0)
187         {
188           q--;
189           usleep(quantum);
190         }
191     }
192   while (q > 0);
193
194   return False; 
195 }
196
197
198 static Bool
199 windows (Display *dpy, Window window, int delay, Bool w95p)
200 {
201   XGCValues gcv;
202   XWindowAttributes xgwa;
203   char *fontname;
204   const char *def_font = "fixed";
205   XFontStruct *font;
206   GC gc;
207
208   const char *w95 =
209     ("@Windows\n"
210      "A fatal exception 0E has occured at F0AD:42494C4C\n"
211      "the current application will be terminated.\n"
212      "\n"
213      "* Press any key to terminate the current application.\n"
214      "* Press CTRL+ALT+DELETE again to restart your computer.\n"
215      "  You will lose any unsaved information in all applications.\n"
216      "\n"
217      "\n"
218      "_Press any key to continue");
219
220   const char *wnt = /* from Jim Niemira <urmane@urmane.org> */
221     ("*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
222    "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
223    "\n"
224    "Dll Base Date Stamp - Name             Dll Base Date Stamp - Name\n"
225    "80100000 2be154c9 - ntoskrnl.exe       80400000 2bc153b0 - hal.dll\n"
226    "80258000 2bd49628 - ncrc710.sys        8025c000 2bd49688 - SCSIPORT.SYS \n"
227    "80267000 2bd49683 - scsidisk.sys       802a6000 2bd496b9 - Fastfat.sys\n"
228    "fa800000 2bd49666 - Floppy.SYS         fa810000 2bd496db - Hpfs_Rec.SYS\n"
229    "fa820000 2bd49676 - Null.SYS           fa830000 2bd4965a - Beep.SYS\n"
230    "fa840000 2bdaab00 - i8042prt.SYS       fa850000 2bd5a020 - SERMOUSE.SYS\n"
231    "fa860000 2bd4966f - kbdclass.SYS       fa870000 2bd49671 - MOUCLASS.SYS\n"
232    "fa880000 2bd9c0be - Videoprt.SYS       fa890000 2bd49638 - NCC1701E.SYS\n"
233    "fa8a0000 2bd4a4ce - Vga.SYS            fa8b0000 2bd496d0 - Msfs.SYS\n"
234    "fa8c0000 2bd496c3 - Npfs.SYS           fa8e0000 2bd496c9 - Ntfs.SYS\n"
235    "fa940000 2bd496df - NDIS.SYS           fa930000 2bd49707 - wdlan.sys\n"
236    "fa970000 2bd49712 - TDI.SYS            fa950000 2bd5a7fb - nbf.sys\n"
237    "fa980000 2bd72406 - streams.sys        fa9b0000 2bd4975f - ubnb.sys\n"
238    "fa9c0000 2bd5bfd7 - usbser.sys         fa9d0000 2bd4971d - netbios.sys\n"
239    "fa9e0000 2bd49678 - Parallel.sys       fa9f0000 2bd4969f - serial.SYS\n"
240    "faa00000 2bd49739 - mup.sys            faa40000 2bd4971f - SMBTRSUP.SYS\n"
241    "faa10000 2bd6f2a2 - srv.sys            faa50000 2bd4971a - afd.sys\n"
242    "faa60000 2bd6fd80 - rdr.sys            faaa0000 2bd49735 - bowser.sys\n"
243    "\n"
244    "Address dword dump Dll Base                                      - Name\n"
245    "801afc20 80106fc0 80106fc0 00000000 00000000 80149905 : "
246      "fa840000 - i8042prt.SYS\n"
247    "801afc24 80149905 80149905 ff8e6b8c 80129c2c ff8e6b94 : "
248      "8025c000 - SCSIPORT.SYS\n"
249    "801afc2c 80129c2c 80129c2c ff8e6b94 00000000 ff8e6b94 : "
250      "80100000 - ntoskrnl.exe\n"
251    "801afc34 801240f2 80124f02 ff8e6df4 ff8e6f60 ff8e6c58 : "
252      "80100000 - ntoskrnl.exe\n"
253    "801afc54 80124f16 80124f16 ff8e6f60 ff8e6c3c 8015ac7e : "
254      "80100000 - ntoskrnl.exe\n"
255    "801afc64 8015ac7e 8015ac7e ff8e6df4 ff8e6f60 ff8e6c58 : "
256      "80100000 - ntoskrnl.exe\n"
257    "801afc70 80129bda 80129bda 00000000 80088000 80106fc0 : "
258      "80100000 - ntoskrnl.exe\n"
259    "\n"
260    "Kernel Debugger Using: COM2 (Port 0x2f8, Baud Rate 19200)\n"
261    "Restart and set the recovery options in the system control panel\n"
262    "or the /CRASHDEBUG system start option. If this message reappears,\n"
263    "contact your system administrator or technical support group."
264      );
265
266   if (!get_boolean_resource((w95p? "doWindows" : "doNT"), "DoWindows"))
267     return False;
268
269   XGetWindowAttributes (dpy, window, &xgwa);
270
271   fontname = get_string_resource ((xgwa.height > 600
272                                    ? (w95p
273                                       ? "windows95.font2"
274                                       : "windowsNT.font2")
275                                    : (w95p
276                                       ? "windows95.font"
277                                       : "windowsNT.font")),
278                                   "Windows.Font");
279   if (!fontname || !*fontname) fontname = (char *)def_font;
280   font = XLoadQueryFont (dpy, fontname);
281   if (!font) font = XLoadQueryFont (dpy, def_font);
282   if (!font) exit(-1);
283   if (fontname && fontname != def_font)
284     free (fontname);
285
286   gcv.font = font->fid;
287   gcv.foreground = get_pixel_resource((w95p
288                                        ? "windows95.foreground"
289                                        : "windowsNT.foreground"),
290                                       "Windows.Foreground",
291                                       dpy, xgwa.colormap);
292   gcv.background = get_pixel_resource((w95p
293                                        ? "windows95.background"
294                                        : "windowsNT.background"),
295                                       "Windows.Background",
296                                       dpy, xgwa.colormap);
297   XSetWindowBackground(dpy, window, gcv.background);
298   XClearWindow(dpy, window);
299
300   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
301
302   if (w95p)
303     draw_string(dpy, window, gc, &gcv, font,
304                 0, 0, xgwa.width, xgwa.height, w95, 0);
305   else
306     draw_string(dpy, window, gc, &gcv, font, 0, 0, 10, 10, wnt, 750);
307
308   XFreeGC(dpy, gc);
309   XSync(dpy, False);
310   bsod_sleep(dpy, delay);
311   XClearWindow(dpy, window);
312   XFreeFont(dpy, font);
313   return True;
314 }
315
316 /* SCO OpenServer 5 panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
317  */
318 static Bool
319 sco (Display *dpy, Window window, int delay)
320 {
321   XGCValues gcv;
322   XWindowAttributes xgwa;
323   char *fontname;
324   const char *def_font = "fixed";
325   XFontStruct *font;
326   GC gc;
327   int lines_1 = 0, lines_2 = 0, lines_3 = 0, lines_4 = 0;
328   const char *s;
329
330   const char *sco_panic_1 =
331     ("Unexpected trap in kernel mode:\n"
332      "\n"
333      "cr0 0x80010013     cr2  0x00000014     cr3 0x00000000  tlb  0x00000000\n"
334      "ss  0x00071054    uesp  0x00012055     efl 0x00080888  ipl  0x00000005\n"
335      "cs  0x00092585     eip  0x00544a4b     err 0x004d4a47  trap 0x0000000E\n"
336      "eax 0x0045474b     ecx  0x0042544b     edx 0x57687920  ebx  0x61726520\n"
337      "esp 0x796f7520     ebp  0x72656164     esi 0x696e6720  edi  0x74686973\n"
338      "ds  0x3f000000     es   0x43494c48     fs  0x43525343  gs   0x4f4d4b53\n"
339      "\n"
340      "PANIC: k_trap - kernel mode trap type 0x0000000E\n"
341      "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n"
342     );
343   const char *sco_panic_2 =
344    ("...............................................................................\n"
345     );
346   const char *sco_panic_3 =
347     ("5023 pages dumped\n"
348      "\n"
349      "\n"
350      );
351   const char *sco_panic_4 =
352     ("**   Safe to Power Off   **\n"
353      "           - or -\n"
354      "** Press Any Key to Reboot **\n"
355     );
356
357   if (!get_boolean_resource("doSCO", "DoSCO"))
358     return False;
359
360   for (s = sco_panic_1; *s; s++) if (*s == '\n') lines_1++;
361   for (s = sco_panic_2; *s; s++) if (*s == '\n') lines_2++;
362   for (s = sco_panic_3; *s; s++) if (*s == '\n') lines_3++;
363   for (s = sco_panic_4; *s; s++) if (*s == '\n') lines_4++;
364
365   XGetWindowAttributes (dpy, window, &xgwa);
366
367   fontname = get_string_resource ((xgwa.height > 600
368                                    ? "sco.font2"
369                                    : "sco.font"),
370                                   "SCO.Font");
371   if (!fontname || !*fontname) fontname = (char *)def_font;
372   font = XLoadQueryFont (dpy, fontname);
373   if (!font) font = XLoadQueryFont (dpy, def_font);
374   if (!font) exit(-1);
375   if (fontname && fontname != def_font)
376     free (fontname);
377
378   gcv.font = font->fid;
379   gcv.foreground = get_pixel_resource(("sco.foreground"),
380                                       "SCO.Foreground",
381                                       dpy, xgwa.colormap);
382   gcv.background = get_pixel_resource(("sco.background"),
383                                       "SCO.Background",
384                                       dpy, xgwa.colormap);
385   XSetWindowBackground(dpy, window, gcv.background);
386   XClearWindow(dpy, window);
387
388   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
389
390   draw_string(dpy, window, gc, &gcv, font,
391               10, xgwa.height - ((lines_1 + lines_2 + lines_3 + lines_4 + 1) *
392                                  (font->ascent + font->descent + 1)),
393               10, 10,
394               sco_panic_1, 0);
395   XSync(dpy, False);
396   for (s = sco_panic_2; *s; s++)
397     {
398       char *ss = strdup(sco_panic_2);
399       ss[s - sco_panic_2] = 0;
400       draw_string(dpy, window, gc, &gcv, font,
401                   10, xgwa.height - ((lines_2 + lines_3 + lines_4 + 1) *
402                                      (font->ascent + font->descent + 1)),
403                   10, 10,
404                   ss, 0);
405       XSync(dpy, False);
406       free(ss);
407       if (bsod_sleep (dpy, -1))
408         goto DONE;
409     }
410
411   draw_string(dpy, window, gc, &gcv, font,
412               10, xgwa.height - ((lines_3 + lines_4 + 1) *
413                                  (font->ascent + font->descent + 1)),
414               10, 10,
415               sco_panic_3, 0);
416   XSync(dpy, False);
417   if (bsod_sleep(dpy, 1))
418     goto DONE;
419   draw_string(dpy, window, gc, &gcv, font,
420               10, xgwa.height - ((lines_4 + 1) *
421                                  (font->ascent + font->descent + 1)),
422               10, 10,
423               sco_panic_4, 0);
424   XSync(dpy, False);
425
426   bsod_sleep(dpy, delay);
427  DONE:
428   XClearWindow(dpy, window);
429   XFreeGC(dpy, gc);
430   XFreeFont(dpy, font);
431   return True;
432 }
433
434
435 /* Linux (sparc) panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
436  */
437 static Bool
438 sparc_linux (Display *dpy, Window window, int delay)
439 {
440   XGCValues gcv;
441   XWindowAttributes xgwa;
442   char *fontname;
443   const char *def_font = "fixed";
444   XFontStruct *font;
445   GC gc;
446   int lines = 1;
447   const char *s;
448
449   const char *linux_panic =
450     ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
451         "Unable to handle kernel paging request at virtual address f0d4a000\n"
452         "tsk->mm->context = 00000014\n"
453         "tsk->mm->pgd = f26b0000\n"
454         "              \\|/ ____ \\|/\n"
455         "              \"@'/ ,. \\`@\"\n"
456         "              /_| \\__/ |_\\\n"
457         "                 \\__U_/\n"
458         "gawk(22827): Oops\n"
459         "PSR: 044010c1 PC: f001c2cc NPC: f001c2d0 Y: 00000000\n"
460         "g0: 00001000 g1: fffffff7 g2: 04401086 g3: 0001eaa0\n"
461         "g4: 000207dc g5: f0130400 g6: f0d4a018 g7: 00000001\n"
462         "o0: 00000000 o1: f0d4a298 o2: 00000040 o3: f1380718\n"
463         "o4: f1380718 o5: 00000200 sp: f1b13f08 ret_pc: f001c2a0\n"
464         "l0: efffd880 l1: 00000001 l2: f0d4a230 l3: 00000014\n"
465         "l4: 0000ffff l5: f0131550 l6: f012c000 l7: f0130400\n"
466         "i0: f1b13fb0 i1: 00000001 i2: 00000002 i3: 0007c000\n"
467         "i4: f01457c0 i5: 00000004 i6: f1b13f70 i7: f0015360\n"
468         "Instruction DUMP:\n"
469     );
470
471   if (!get_boolean_resource("doSparcLinux", "DoSparcLinux"))
472     return False;
473
474   for (s = linux_panic; *s; s++) if (*s == '\n') lines++;
475
476   XGetWindowAttributes (dpy, window, &xgwa);
477
478   fontname = get_string_resource ((xgwa.height > 600
479                                    ? "sparclinux.font2"
480                                    : "sparclinux.font"),
481                                   "SparcLinux.Font");
482   if (!fontname || !*fontname) fontname = (char *)def_font;
483   font = XLoadQueryFont (dpy, fontname);
484   if (!font) font = XLoadQueryFont (dpy, def_font);
485   if (!font) exit(-1);
486   if (fontname && fontname != def_font)
487     free (fontname);
488
489   gcv.font = font->fid;
490   gcv.foreground = get_pixel_resource(("sparclinux.foreground"),
491                                       "SparcLinux.Foreground",
492                                       dpy, xgwa.colormap);
493   gcv.background = get_pixel_resource(("sparclinux.background"),
494                                       "SparcLinux.Background",
495                                       dpy, xgwa.colormap);
496   XSetWindowBackground(dpy, window, gcv.background);
497   XClearWindow(dpy, window);
498
499   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
500
501   draw_string(dpy, window, gc, &gcv, font,
502               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
503               10, 10,
504               linux_panic, 0);
505   XFreeGC(dpy, gc);
506   XSync(dpy, False);
507   bsod_sleep(dpy, delay);
508   XClearWindow(dpy, window);
509   XFreeFont(dpy, font);
510   return True;
511 }
512
513 /* BSD Panic by greywolf@starwolf.com - modeled after the Linux panic above.
514    By Grey Wolf <greywolf@siteROCK.com>
515  */
516 static Bool
517 bsd (Display *dpy, Window window, int delay)
518 {
519   XGCValues gcv;
520   XWindowAttributes xgwa;
521   char *fontname;
522   const char *def_font = "fixed";
523   XFontStruct *font;
524   GC gc;
525   int lines = 1;
526   int i, n, b;
527   const char *rbstr, *panicking;
528   char syncing[80], bbuf[5], *bp;
529
530   const char *panicstr[] =
531    {"panic: ifree: freeing free inode",
532     "panic: blkfree: freeing free block",
533     "panic: improbability coefficient below zero",
534     "panic: cgsixmmap",
535     "panic: crazy interrupts",
536     "panic: nmi",
537     "panic: attempted windows install",
538     "panic: don't",
539     "panic: free inode isn't",
540     "panic: cpu_fork: curproc",
541     "panic: malloc: out of space in kmem_map",
542     "panic: vogon starship detected",
543     "panic: teleport chamber: out of order",
544     "panic: Brain fried - core dumped"};
545      
546   if (!get_boolean_resource("doBSD", "DoBSD"))
547     return False;
548
549   for (i = 0; i < sizeof(syncing); i++)
550     syncing[i] = 0;
551
552   i = (random() & 0xffff) % (sizeof(panicstr) / sizeof(*panicstr));
553
554   panicking = panicstr[i];
555   strcpy(syncing, "Syncing disks: ");
556
557   b = (random() & 0xff) % 40;
558   for (n = 0; (n < 20) && (b > 0); n++)
559     {
560       if (i)
561         {
562           i = (random() & 0x7);
563           b -= (random() & 0xff) % 20;
564           if (b < 0)
565             b = 0;
566         }
567       sprintf (bbuf, "%d ", b);
568       strcat (syncing, bbuf);
569     }
570
571   if (b)
572     rbstr = "damn!";
573   else
574     rbstr = "sunk!";
575
576   lines = 5;
577
578   XGetWindowAttributes (dpy, window, &xgwa);
579
580   fontname = get_string_resource ((xgwa.height > 600
581                                    ? "bsd.font2"
582                                    : "bsd.font"),
583                                   "BSD.Font");
584   if (!fontname || !*fontname) fontname = (char *)def_font;
585   font = XLoadQueryFont (dpy, fontname);
586   if (!font) font = XLoadQueryFont (dpy, def_font);
587   if (!font) exit(-1);
588   if (fontname && fontname != def_font)
589     free (fontname);
590
591   gcv.font = font->fid;
592   gcv.foreground = get_pixel_resource(("bsd.foreground"),
593                                       "BSD.Foreground",
594                                       dpy, xgwa.colormap);
595   gcv.background = get_pixel_resource(("bsd.background"),
596                                       "BSD.Background",
597                                       dpy, xgwa.colormap);
598   XSetWindowBackground(dpy, window, gcv.background);
599   XClearWindow(dpy, window);
600
601   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
602
603   draw_string(dpy, window, gc, &gcv, font,
604               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
605               10, 10,
606               panicking, 0);
607   XSync(dpy, False);
608   lines--;
609
610   for (bp = syncing; *bp;)
611     {
612       char *bsd_bufs, oc = 0;
613       for (;*bp && (*bp != ' '); bp++)
614         ;
615       if (*bp == ' ')
616         {
617           oc = *bp;
618           *bp = 0;
619         }
620       bsd_bufs = strdup(syncing);
621       draw_string(dpy, window, gc, &gcv, font,
622                   10,
623                   xgwa.height - (lines * (font->ascent + font->descent + 1)),
624                   10, 10,
625                   bsd_bufs, 0);
626       XSync(dpy, False);
627       free(bsd_bufs);
628       if (oc)
629         *bp = oc;
630       if (bsod_sleep(dpy, -1))
631         goto DONE;
632       bp++;
633     }
634
635   lines--;
636   
637   draw_string(dpy, window, gc, &gcv, font,
638               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
639               10, 10,
640               rbstr, 0);
641   lines--;
642   draw_string(dpy, window, gc, &gcv, font,
643               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
644               10, 10,
645               "Rebooting", 0);
646
647   XFreeGC(dpy, gc);
648   XSync(dpy, False);
649   bsod_sleep(dpy, delay);
650
651 DONE:
652   XClearWindow(dpy, window);
653   XFreeFont(dpy, font);
654   return True;
655 }
656
657 static Bool
658 amiga (Display *dpy, Window window, int delay)
659 {
660   XGCValues gcv;
661   XWindowAttributes xgwa;
662   char *fontname;
663   const char *def_font = "fixed";
664   XFontStruct *font;
665   GC gc, gc2;
666   int height;
667   unsigned long fg, bg, bg2;
668   Pixmap pixmap = 0;
669   int pix_w = 0, pix_h = 0;
670
671   const char *string =
672     ("_Software failure.  Press left mouse button to continue.\n"
673      "_Guru Meditation #00000003.00C01570");
674
675   if (!get_boolean_resource("doAmiga", "DoAmiga"))
676     return False;
677
678   XGetWindowAttributes (dpy, window, &xgwa);
679
680   fontname = get_string_resource ((xgwa.height > 600
681                                    ? "amiga.font2" : "amiga.font"),
682                                   "Amiga.Font");
683   if (!fontname || !*fontname) fontname = (char *)def_font;
684   font = XLoadQueryFont (dpy, fontname);
685   if (!font) font = XLoadQueryFont (dpy, def_font);
686   if (!font) exit(-1);
687   if (fontname && fontname != def_font)
688     free (fontname);
689
690   gcv.font = font->fid;
691   fg = gcv.foreground = get_pixel_resource("amiga.foreground",
692                                            "Amiga.Foreground",
693                                            dpy, xgwa.colormap);
694   bg = gcv.background = get_pixel_resource("amiga.background",
695                                            "Amiga.Background",
696                                            dpy, xgwa.colormap);
697   bg2 = get_pixel_resource("amiga.background2", "Amiga.Background",
698                            dpy, xgwa.colormap);
699   XSetWindowBackground(dpy, window, bg2);
700   XClearWindow(dpy, window);
701
702   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
703   gcv.background = fg; gcv.foreground = bg;
704   gc2 = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
705
706   height = (font->ascent + font->descent) * 6;
707
708 #ifdef HAVE_XPM
709   {
710     XpmAttributes xpmattrs;
711     int result;
712     xpmattrs.valuemask = 0;
713
714 # ifdef XpmCloseness
715     xpmattrs.valuemask |= XpmCloseness;
716     xpmattrs.closeness = 40000;
717 # endif
718 # ifdef XpmVisual
719     xpmattrs.valuemask |= XpmVisual;
720     xpmattrs.visual = xgwa.visual;
721 # endif
722 # ifdef XpmDepth
723     xpmattrs.valuemask |= XpmDepth;
724     xpmattrs.depth = xgwa.depth;
725 # endif
726 # ifdef XpmColormap
727     xpmattrs.valuemask |= XpmColormap;
728     xpmattrs.colormap = xgwa.colormap;
729 # endif
730
731     result = XpmCreatePixmapFromData(dpy, window, amiga_hand,
732                                      &pixmap, 0 /* mask */, &xpmattrs);
733     if (!pixmap || (result != XpmSuccess && result != XpmColorError))
734       pixmap = 0;
735     pix_w = xpmattrs.width;
736     pix_h = xpmattrs.height;
737   }
738 #endif /* HAVE_XPM */
739
740   if (pixmap && xgwa.height > 600)      /* scale up the bitmap */
741     {
742       pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
743                              pixmap, pix_w, pix_h);
744       pix_w *= 2;
745       pix_h *= 2;
746     }
747
748   if (pixmap)
749     {
750       int x = (xgwa.width - pix_w) / 2;
751       int y = ((xgwa.height - pix_h) / 2);
752       XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
753
754       XSync(dpy, False);
755       bsod_sleep(dpy, 2);
756
757       XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y + height);
758       XClearArea(dpy, window, 0, 0, xgwa.width, y + height, False);
759       XFreePixmap(dpy, pixmap);
760     }
761
762   XFillRectangle(dpy, window, gc2, 0, 0, xgwa.width, height);
763   draw_string(dpy, window, gc, &gcv, font, 0, 0, xgwa.width, height, string,0);
764
765   {
766     GC gca = gc;
767     while (delay > 0)
768       {
769         XFillRectangle(dpy, window, gca, 0, 0, xgwa.width, font->ascent);
770         XFillRectangle(dpy, window, gca, 0, 0, font->ascent, height);
771         XFillRectangle(dpy, window, gca, xgwa.width-font->ascent, 0,
772                        font->ascent, height);
773         XFillRectangle(dpy, window, gca, 0, height-font->ascent, xgwa.width,
774                        font->ascent);
775         gca = (gca == gc ? gc2 : gc);
776         XSync(dpy, False);
777         if (bsod_sleep(dpy, 1))
778           break;
779         delay--;
780       }
781   }
782
783   XFreeGC(dpy, gc);
784   XFreeGC(dpy, gc2);
785   XSync(dpy, False);
786   XClearWindow(dpy, window);
787   XFreeFont(dpy, font);
788   return True;
789 }
790
791
792 /* Atari ST, by Marcus Herbert <rhoenie@nobiscum.de>
793    Marcus had this to say:
794
795         Though I still have my Atari somewhere, I hardly remember
796         the meaning of the bombs. I think 9 bombs was "bus error" or
797         something like that.  And you often had a few bombs displayed
798         quickly and then the next few ones coming up step by step.
799         Perhaps somebody else can tell you more about it..  its just
800         a quick hack :-}
801  */
802 static Bool
803 atari (Display *dpy, Window window, int delay)
804 {
805         
806   XGCValues gcv;
807   XWindowAttributes xgwa;
808   const char *def_font = "fixed";
809   XFontStruct *font;
810   GC gc;
811   Pixmap pixmap = 0;
812   int pix_w = atari_width;
813   int pix_h = atari_height;
814   int offset;
815   int i, x, y;
816
817   if (!get_boolean_resource("doAtari", "DoAtari"))
818     return False;
819
820   XGetWindowAttributes (dpy, window, &xgwa);
821
822   font = XLoadQueryFont (dpy, def_font);
823   if (!font) exit(-1);
824                 
825   gcv.font = font->fid;
826   gcv.foreground = get_pixel_resource("atari.foreground", "Atari.Foreground",
827                                       dpy, xgwa.colormap);
828   gcv.background = get_pixel_resource("atari.background", "Atari.Background",
829                                       dpy, xgwa.colormap);
830
831   XSetWindowBackground(dpy, window, gcv.background);
832   XClearWindow(dpy, window);
833
834   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
835
836   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) atari_bits,
837                                        pix_w, pix_h,
838                                        gcv.foreground, gcv.background,
839                                        xgwa.depth);
840   pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
841                          pixmap, pix_w, pix_h);
842   pix_w *= 2;
843   pix_h *= 2;
844
845   offset = pix_w + 2;
846   x = 5;
847   y = (xgwa.height - (xgwa.height / 5));
848   if (y < 0) y = 0;
849
850   for (i=0 ; i<7 ; i++) {
851     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
852               (x + (i*offset)), y);
853   }  
854   
855   for (i=7 ; i<10 ; i++) {
856     if (bsod_sleep(dpy, 1))
857       goto DONE;
858     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
859               (x + (i*offset)), y);
860   }
861
862   bsod_sleep(dpy, delay);
863  DONE:
864   XFreePixmap(dpy, pixmap);
865   XFreeGC(dpy, gc);
866   XSync(dpy, False);
867   XClearWindow(dpy, window);
868   XFreeFont(dpy, font);
869   return True;
870 }
871
872
873 static Bool
874 mac (Display *dpy, Window window, int delay)
875 {
876   XGCValues gcv;
877   XWindowAttributes xgwa;
878   char *fontname;
879   const char *def_font = "fixed";
880   XFontStruct *font;
881   GC gc;
882   Pixmap pixmap = 0;
883   int pix_w = mac_width;
884   int pix_h = mac_height;
885   int offset = mac_height * 4;
886   int i;
887
888   const char *string = ("0 0 0 0 0 0 0 F\n"
889                         "0 0 0 0 0 0 0 3");
890
891   if (!get_boolean_resource("doMac", "DoMac"))
892     return False;
893
894   XGetWindowAttributes (dpy, window, &xgwa);
895
896   fontname = get_string_resource ("mac.font", "Mac.Font");
897   if (!fontname || !*fontname) fontname = (char *)def_font;
898   font = XLoadQueryFont (dpy, fontname);
899   if (!font) font = XLoadQueryFont (dpy, def_font);
900   if (!font) exit(-1);
901   if (fontname && fontname != def_font)
902     free (fontname);
903
904   gcv.font = font->fid;
905   gcv.foreground = get_pixel_resource("mac.foreground", "Mac.Foreground",
906                                       dpy, xgwa.colormap);
907   gcv.background = get_pixel_resource("mac.background", "Mac.Background",
908                                       dpy, xgwa.colormap);
909   XSetWindowBackground(dpy, window, gcv.background);
910   XClearWindow(dpy, window);
911
912   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
913
914   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits,
915                                        mac_width, mac_height,
916                                        gcv.foreground,
917                                        gcv.background,
918                                        xgwa.depth);
919
920   for(i = 0; i < 2; i++)
921     {
922       pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
923                              pixmap, pix_w, pix_h);
924       pix_w *= 2; pix_h *= 2;
925     }
926
927   {
928     int x = (xgwa.width - pix_w) / 2;
929     int y = (((xgwa.height + offset) / 2) -
930              pix_h -
931              (font->ascent + font->descent) * 2);
932     if (y < 0) y = 0;
933     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
934     XFreePixmap(dpy, pixmap);
935   }
936
937   draw_string(dpy, window, gc, &gcv, font, 0, 0,
938               xgwa.width, xgwa.height + offset, string, 0);
939
940   XFreeGC(dpy, gc);
941   XSync(dpy, False);
942   bsod_sleep(dpy, delay);
943   XClearWindow(dpy, window);
944   XFreeFont(dpy, font);
945   return True;
946 }
947
948 static Bool
949 macsbug (Display *dpy, Window window, int delay)
950 {
951   XGCValues gcv;
952   XWindowAttributes xgwa;
953   char *fontname;
954   const char *def_font = "fixed";
955   XFontStruct *font;
956   GC gc, gc2;
957
958   int char_width, line_height;
959   int col_right, row_top, row_bottom, page_right, page_bottom, body_top;
960   int xoff, yoff;
961
962   const char *left = ("    SP     \n"
963                       " 04EB0A58  \n"
964                       "58 00010000\n"
965                       "5C 00010000\n"
966                       "   ........\n"
967                       "60 00000000\n"
968                       "64 000004EB\n"
969                       "   ........\n"
970                       "68 0000027F\n"
971                       "6C 2D980035\n"
972                       "   ....-..5\n"
973                       "70 00000054\n"
974                       "74 0173003E\n"
975                       "   ...T.s.>\n"
976                       "78 04EBDA76\n"
977                       "7C 04EBDA8E\n"
978                       "   .S.L.a.U\n"
979                       "80 00000000\n"
980                       "84 000004EB\n"
981                       "   ........\n"
982                       "88 00010000\n"
983                       "8C 00010000\n"
984                       "   ...{3..S\n"
985                       "\n"
986                       "\n"
987                       " CurApName \n"
988                       "  Finder   \n"
989                       "\n"
990                       " 32-bit VM \n"
991                       "SR Smxnzvc0\n"
992                       "D0 04EC0062\n"
993                       "D1 00000053\n"
994                       "D2 FFFF0100\n"
995                       "D3 00010000\n"
996                       "D4 00010000\n"
997                       "D5 04EBDA76\n"
998                       "D6 04EBDA8E\n"
999                       "D7 00000001\n"
1000                       "\n"
1001                       "A0 04EBDA76\n"
1002                       "A1 04EBDA8E\n"
1003                       "A2 A0A00060\n"
1004                       "A3 027F2D98\n"
1005                       "A4 027F2E58\n"
1006                       "A5 04EC04F0\n"
1007                       "A6 04EB0A86\n"
1008                       "A7 04EB0A58");
1009   const char *bottom = ("  _A09D\n"
1010                         "     +00884    40843714     #$0700,SR         "
1011                         "                  ; A973        | A973\n"
1012                         "     +00886    40843765     *+$0400           "
1013                         "                                | 4A1F\n"
1014                         "     +00888    40843718     $0004(A7),([0,A7[)"
1015                         "                  ; 04E8D0AE    | 66B8");
1016
1017 #if 0
1018   const char *body = ("Bus Error at 4BF6D6CC\n"
1019                       "while reading word from 4BF6D6CC in User data space\n"
1020                       " Unable to access that address\n"
1021                       "  PC: 2A0DE3E6\n"
1022                       "  Frame Type: B008");
1023 #else
1024   const char * body = ("PowerPC unmapped memory exception at 003AFDAC "
1025                                                 "BowelsOfTheMemoryMgr+04F9C\n"
1026                       " Calling chain using A6/R1 links\n"
1027                       "  Back chain  ISA  Caller\n"
1028                       "  00000000    PPC  28C5353C  __start+00054\n"
1029                       "  24DB03C0    PPC  28B9258C  main+0039C\n"
1030                       "  24DB0350    PPC  28B9210C  MainEvent+00494\n"
1031                       "  24DB02B0    PPC  28B91B40  HandleEvent+00278\n"
1032                       "  24DB0250    PPC  28B83DAC  DoAppleEvent+00020\n"
1033                       "  24DB0210    PPC  FFD3E5D0  "
1034                                                 "AEProcessAppleEvent+00020\n"
1035                       "  24DB0132    68K  00589468\n"
1036                       "  24DAFF8C    68K  00589582\n"
1037                       "  24DAFF26    68K  00588F70\n"
1038                       "  24DAFEB3    PPC  00307098  "
1039                                                 "EmToNatEndMoveParams+00014\n"
1040                       "  24DAFE40    PPC  28B9D0B0  DoScript+001C4\n"
1041                       "  24DAFDD0    PPC  28B9C35C  RunScript+00390\n"
1042                       "  24DAFC60    PPC  28BA36D4  run_perl+000E0\n"
1043                       "  24DAFC10    PPC  28BC2904  perl_run+002CC\n"
1044                       "  24DAFA80    PPC  28C18490  Perl_runops+00068\n"
1045                       "  24DAFA30    PPC  28BE6CC0  Perl_pp_backtick+000FC\n"
1046                       "  24DAF9D0    PPC  28BA48B8  Perl_my_popen+00158\n"
1047                       "  24DAF980    PPC  28C5395C  sfclose+00378\n"
1048                       "  24DAF930    PPC  28BA568C  free+0000C\n"
1049                       "  24DAF8F0    PPC  28BA6254  pool_free+001D0\n"
1050                       "  24DAF8A0    PPC  FFD48F14  DisposePtr+00028\n"
1051                       "  24DAF7C9    PPC  00307098  "
1052                                                 "EmToNatEndMoveParams+00014\n"
1053                       "  24DAF780    PPC  003AA180  __DisposePtr+00010");
1054 #endif
1055
1056   const char *s;
1057   int body_lines = 1;
1058
1059   if (!get_boolean_resource("doMacsBug", "DoMacsBug"))
1060     return False;
1061
1062   for (s = body; *s; s++) if (*s == '\n') body_lines++;
1063
1064   XGetWindowAttributes (dpy, window, &xgwa);
1065
1066   fontname = get_string_resource ((xgwa.height > 850
1067                                    ? "macsbug.font3"
1068                                    : (xgwa.height > 700
1069                                       ? "macsbug.font2"
1070                                       : "macsbug.font")),
1071                                   "MacsBug.Font");
1072   if (!fontname || !*fontname) fontname = (char *)def_font;
1073   font = XLoadQueryFont (dpy, fontname);
1074   if (!font) font = XLoadQueryFont (dpy, def_font);
1075   if (!font) exit(-1);
1076   if (fontname && fontname != def_font)
1077     free (fontname);
1078
1079   gcv.font = font->fid;
1080   gcv.foreground = get_pixel_resource("macsbug.foreground",
1081                                       "MacsBug.Foreground",
1082                                       dpy, xgwa.colormap);
1083   gcv.background = get_pixel_resource("macsbug.background",
1084                                       "MacsBug.Background",
1085                                       dpy, xgwa.colormap);
1086
1087   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
1088
1089   gcv.foreground = gcv.background;
1090   gc2 = XCreateGC(dpy, window, GCForeground, &gcv);
1091
1092   XSetWindowBackground(dpy, window,
1093                        get_pixel_resource("macsbug.borderColor",
1094                                           "MacsBug.BorderColor",
1095                                           dpy, xgwa.colormap));
1096   XClearWindow(dpy, window);
1097
1098   char_width = (font->per_char
1099                 ? font->per_char['n'-font->min_char_or_byte2].width
1100                 : font->min_bounds.width);
1101   line_height = font->ascent + font->descent + 1;
1102
1103   col_right = char_width * 12;
1104   page_bottom = line_height * 47;
1105
1106   if (page_bottom > xgwa.height) page_bottom = xgwa.height;
1107
1108   row_bottom = page_bottom - line_height;
1109   row_top = row_bottom - (line_height * 4);
1110   page_right = col_right + (char_width * 88);
1111   body_top = row_top - (line_height * body_lines);
1112
1113   page_bottom += 2;
1114   row_bottom += 2;
1115   body_top -= 4;
1116
1117   xoff = (xgwa.width - page_right) / 2;
1118   yoff = (xgwa.height - page_bottom) / 2;
1119   if (xoff < 0) xoff = 0;
1120   if (yoff < 0) yoff = 0;
1121
1122   XFillRectangle(dpy, window, gc2, xoff, yoff, page_right, page_bottom);
1123
1124   draw_string(dpy, window, gc, &gcv, font, xoff, yoff, 10, 10, left, 0);
1125   draw_string(dpy, window, gc, &gcv, font, xoff+col_right, yoff+row_top,
1126               10, 10, bottom, 0);
1127
1128   XFillRectangle(dpy, window, gc, xoff + col_right, yoff, 2, page_bottom);
1129   XDrawLine(dpy, window, gc,
1130             xoff+col_right, yoff+row_top, xoff+page_right, yoff+row_top);
1131   XDrawLine(dpy, window, gc,
1132             xoff+col_right, yoff+row_bottom, xoff+page_right, yoff+row_bottom);
1133   XDrawRectangle(dpy, window, gc,  xoff, yoff, page_right, page_bottom);
1134
1135   if (body_top > 4)
1136     body_top = 4;
1137
1138   draw_string(dpy, window, gc, &gcv, font,
1139               xoff + col_right + char_width, yoff + body_top, 10, 10, body,
1140               500);
1141
1142   while (delay > 0)
1143     {
1144       XDrawLine(dpy, window, gc,
1145                 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
1146                 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
1147       XSync(dpy, False);
1148       usleep(666666L);
1149       XDrawLine(dpy, window, gc2,
1150                 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
1151                 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
1152       XSync(dpy, False);
1153       usleep(333333L);
1154       if (bsod_sleep(dpy, 0))
1155         break;
1156       delay--;
1157     }
1158
1159   XFreeGC(dpy, gc);
1160   XFreeGC(dpy, gc2);
1161   XClearWindow(dpy, window);
1162   XFreeFont(dpy, font);
1163   return True;
1164 }
1165
1166 \f
1167 /* blit damage
1168  *
1169  * by Martin Pool <mbp@samba.org>, Feb 2000.
1170  *
1171  * This is meant to look like the preferred failure mode of NCD
1172  * Xterms.  The parameters for choosing what to copy where might not
1173  * be quite right, but it looks about ugly enough.
1174  */
1175 static Bool
1176 blitdamage (Display *dpy, Window window, int delay)
1177 {
1178   XGCValues gcv;
1179   XWindowAttributes xwa;
1180   GC gc0;
1181   int i;
1182   int delta_x = 0, delta_y = 0;
1183   int w, h;
1184   int chunk_h, chunk_w;
1185   int steps;
1186   long gc_mask = 0;
1187   int src_x, src_y;
1188   int x, y;
1189   
1190   if (!get_boolean_resource("doBlitDamage", "DoBlitDamage"))
1191     return False;
1192
1193   XGetWindowAttributes(dpy, window, &xwa);
1194
1195   grab_screen_image(xwa.screen, window);
1196
1197   w = xwa.width;
1198   h = xwa.height;
1199
1200   gc_mask = GCForeground;
1201   
1202   gcv.plane_mask = random();
1203   gc_mask |= GCPlaneMask;
1204   
1205   gc0 = XCreateGC(dpy, window, gc_mask, &gcv);
1206
1207   steps = 50;
1208   chunk_w = w / (random() % 1 + 1);
1209   chunk_h = h / (random() % 1 + 1);
1210   if (random() & 0x1000) 
1211     delta_y = random() % 600;
1212   if (!delta_y || (random() & 0x2000))
1213     delta_x = random() % 600;
1214   src_x = 0; 
1215   src_y = 0; 
1216   x = 0;
1217   y = 0;
1218   
1219   for (i = 0; i < steps; i++) {
1220     if (x + chunk_w > w) 
1221       x -= w;
1222     else
1223       x += delta_x;
1224     
1225     if (y + chunk_h > h)
1226       y -= h;
1227     else
1228       y += delta_y;
1229     
1230     XCopyArea(dpy, window, window, gc0,
1231               src_x, src_y, 
1232               chunk_w, chunk_h,
1233               x, y);
1234
1235     bsod_sleep(dpy, 0);
1236   }
1237
1238   bsod_sleep(dpy, delay);
1239
1240   XFreeGC(dpy, gc0);
1241
1242   return True;
1243 }
1244
1245
1246 \f
1247 char *progclass = "BSOD";
1248
1249 char *defaults [] = {
1250   "*delay:                 30",
1251
1252   "*doWindows:             True",
1253   "*doNT:                  True",
1254   "*doAmiga:               True",
1255   "*doMac:                 True",
1256   "*doAtari:               False",      /* boring */
1257   "*doMacsBug:             True",
1258   "*doSCO:                 True",
1259   "*doBSD:                 False",      /* boring */
1260   "*doSparcLinux:          False",      /* boring */
1261   "*doBlitDamage:          True",
1262
1263   ".Windows.font:          -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1264   ".Windows.font2:         -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
1265   ".Windows.foreground:    White",
1266   ".Windows.background:    Blue",
1267
1268   ".Amiga.font:            -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1269   ".Amiga.font2:           -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
1270   ".Amiga.foreground:      Red",
1271   ".Amiga.background:      Black",
1272   ".Amiga.background2:     White",
1273
1274   ".Mac.font:              -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1275   ".Mac.foreground:        PaleTurquoise1",
1276   ".Mac.background:        Black",
1277
1278   ".Atari.foreground:      Black",
1279   ".Atari.background:      White",
1280
1281   ".MacsBug.font:          -*-courier-medium-r-*-*-*-100-*-*-m-*-*-*",
1282   ".MacsBug.font2:         -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1283   ".MacsBug.font3:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
1284   ".MacsBug.foreground:    Black",
1285   ".MacsBug.background:    White",
1286   ".MacsBug.borderColor:   #AAAAAA",
1287   
1288   ".SCO.font:              -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1289   ".SCO.font2:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
1290   ".SCO.foreground:        White",
1291   ".SCO.background:        Black",
1292   
1293   ".SparcLinux.font:       -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1294   ".SparcLinux.font2:      -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
1295   ".SparcLinux.foreground: White",
1296   ".SparcLinux.background: Black",
1297
1298   ".BSD.font:               vga",
1299   ".BSD.font:               -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1300   ".BSD.font2:              -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
1301 /* ".BSD.font2:             -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*", */
1302   ".BSD.foreground:         #c0c0c0",
1303   ".BSD.background:         Black",
1304   0
1305 };
1306
1307 XrmOptionDescRec options [] = {
1308   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
1309   { 0, 0, 0, 0 }
1310 };
1311
1312
1313 void
1314 screenhack (Display *dpy, Window window)
1315 {
1316   int loop = 0;
1317   int i = -1;
1318   int j = -1;
1319   int delay = get_integer_resource ("delay", "Integer");
1320   if (delay < 3) delay = 3;
1321
1322   if (!get_boolean_resource ("root", "Boolean"))
1323     {
1324       XWindowAttributes xgwa;
1325       XGetWindowAttributes (dpy, window, &xgwa);
1326       XSelectInput (dpy, window,
1327                     xgwa.your_event_mask | KeyPressMask | ButtonPressMask);
1328     }
1329
1330   while (1)
1331     {
1332       Bool did;
1333       do {  i = (random() & 0xFF) % 10; } while (i == j);
1334       switch (i)
1335         {
1336         case 0: did = windows(dpy, window, delay, True); break;
1337         case 1: did = windows(dpy, window, delay, False); break;
1338         case 2: did = amiga(dpy, window, delay); break;
1339         case 3: did = mac(dpy, window, delay); break;
1340         case 4: did = macsbug(dpy, window, delay); break;
1341         case 5: did = sco(dpy, window, delay); break;
1342         case 6: did = sparc_linux(dpy, window, delay); break;
1343         case 7: did = bsd(dpy, window, delay); break;
1344         case 8: did = atari(dpy, window, delay); break;
1345         case 9: did = blitdamage(dpy, window, delay); break;
1346         default: abort(); break;
1347         }
1348       loop++;
1349       if (loop > 100) j = -1;
1350       if (loop > 200) exit(-1);
1351       if (!did) continue;
1352       XSync (dpy, False);
1353       j = i;
1354       loop = 0;
1355     }
1356 }