http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.02.tar.gz
[xscreensaver] / hacks / bsod.c
1 /* xscreensaver, Copyright (c) 1998-2001 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  *      -  Should randomize the various hex numbers printed.
19  */
20
21 #include "screenhack.h"
22 #include "xpm-pixmap.h"
23 #include <stdio.h>
24 #include <X11/Xutil.h>
25
26
27 #include "images/amiga.xpm"
28 #include "images/atari.xbm"
29 #include "images/mac.xbm"
30 #include "images/macbomb.xbm"
31
32
33 static int
34 draw_string (Display *dpy, Window window, GC gc, XGCValues *gcv,
35              XFontStruct *font,
36              int xoff, int yoff,
37              int win_width, int win_height,
38              const char *string, int delay)
39 {
40   int x, y;
41   int width = 0, height = 0, cw = 0;
42   int char_width, line_height;
43
44   const char *s = string;
45   const char *se = string;
46
47   /* This pretty much assumes fixed-width fonts */
48   char_width = (font->per_char
49                 ? font->per_char['n'-font->min_char_or_byte2].width
50                 : font->min_bounds.width);
51   line_height = font->ascent + font->descent + 1;
52
53   while (1)
54     {
55       if (*s == '\n' || !*s)
56         {
57           height++;
58           if (cw > width) width = cw;
59           cw = 0;
60           if (!*s) break;
61         }
62       else
63         cw++;
64       s++;
65     }
66
67   x = (win_width - (width * char_width)) / 2;
68   y = (win_height - (height * line_height)) / 2;
69
70   if (x < 0) x = 2;
71   if (y < 0) y = 2;
72
73   x += xoff;
74   y += yoff;
75
76   se = s = string;
77   while (1)
78     {
79       if (*s == '\n' || !*s)
80         {
81           int off = 0;
82           Bool flip = False;
83
84           if (*se == '@' || *se == '_')
85             {
86               if (*se == '@') flip = True;
87               se++;
88               off = (char_width * (width - (s - se))) / 2;
89             }
90
91           if (flip)
92             {
93               XSetForeground(dpy, gc, gcv->background);
94               XSetBackground(dpy, gc, gcv->foreground);
95             }
96
97           if (s != se)
98             XDrawImageString(dpy, window, gc, x+off, y+font->ascent, se, s-se);
99
100           if (flip)
101             {
102               XSetForeground(dpy, gc, gcv->foreground);
103               XSetBackground(dpy, gc, gcv->background);
104             }
105
106           se = s;
107           y += line_height;
108           if (!*s) break;
109           se = s+1;
110
111           if (delay)
112             {
113               XSync(dpy, False);
114               usleep(delay);
115             }
116         }
117       s++;
118     }
119
120   return width * char_width;
121 }
122
123
124 static Pixmap
125 double_pixmap(Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
126              int pix_w, int pix_h)
127 {
128   int x, y;
129   Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
130   XImage *i1 = XGetImage(dpy, pixmap, 0, 0, pix_w, pix_h, ~0L, ZPixmap);
131   XImage *i2 = XCreateImage(dpy, visual, depth, ZPixmap, 0, 0,
132                             pix_w*2, pix_h*2, 8, 0);
133   i2->data = (char *) calloc(i2->height, i2->bytes_per_line);
134   for (y = 0; y < pix_h; y++)
135     for (x = 0; x < pix_w; x++)
136       {
137         unsigned long p = XGetPixel(i1, x, y);
138         XPutPixel(i2, x*2,   y*2,   p);
139         XPutPixel(i2, x*2+1, y*2,   p);
140         XPutPixel(i2, x*2,   y*2+1, p);
141         XPutPixel(i2, x*2+1, y*2+1, p);
142       }
143   free(i1->data); i1->data = 0;
144   XDestroyImage(i1);
145   XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
146   free(i2->data); i2->data = 0;
147   XDestroyImage(i2);
148   XFreePixmap(dpy, pixmap);
149   return p2;
150 }
151
152
153 /* Sleep for N seconds and return False.  But if a key or mouse event is
154    seen, discard all pending key or mouse events, and return True.
155  */
156 static Bool
157 bsod_sleep(Display *dpy, int seconds)
158 {
159   int q = seconds * 4;
160   int quantum = 250000;
161
162   if (seconds == -1)
163     q = 1, quantum = 100000;
164
165   do
166     {
167       XSync(dpy, False);
168       while (XPending (dpy))
169         {
170           XEvent event;
171           XNextEvent (dpy, &event);
172           if (event.xany.type == ButtonPress)
173             return True;
174           if (event.xany.type == KeyPress)
175             {
176               KeySym keysym;
177               char c = 0;
178               XLookupString (&event.xkey, &c, 1, &keysym, 0);
179               if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
180                 return True;
181             }
182           screenhack_handle_event (dpy, &event);
183         }
184
185       if (q > 0)
186         {
187           q--;
188           usleep(quantum);
189         }
190     }
191   while (q > 0);
192
193   return False; 
194 }
195
196
197 static Bool
198 windows (Display *dpy, Window window, int delay, int which)
199 {
200   XGCValues gcv;
201   XWindowAttributes xgwa;
202   char *fontname;
203   const char *def_font = "fixed";
204   XFontStruct *font;
205   GC gc;
206
207   const char *w95 =
208     ("@Windows\n"
209      "A fatal exception 0E has occured at F0AD:42494C4C\n"
210      "the current application will be terminated.\n"
211      "\n"
212      "* Press any key to terminate the current application.\n"
213      "* Press CTRL+ALT+DELETE again to restart your computer.\n"
214      "  You will lose any unsaved information in all applications.\n"
215      "\n"
216      "\n"
217      "_Press any key to continue");
218
219   const char *wnt = /* from Jim Niemira <urmane@urmane.org> */
220     ("*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
221    "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
222    "\n"
223    "Dll Base Date Stamp - Name             Dll Base Date Stamp - Name\n"
224    "80100000 2be154c9 - ntoskrnl.exe       80400000 2bc153b0 - hal.dll\n"
225    "80258000 2bd49628 - ncrc710.sys        8025c000 2bd49688 - SCSIPORT.SYS \n"
226    "80267000 2bd49683 - scsidisk.sys       802a6000 2bd496b9 - Fastfat.sys\n"
227    "fa800000 2bd49666 - Floppy.SYS         fa810000 2bd496db - Hpfs_Rec.SYS\n"
228    "fa820000 2bd49676 - Null.SYS           fa830000 2bd4965a - Beep.SYS\n"
229    "fa840000 2bdaab00 - i8042prt.SYS       fa850000 2bd5a020 - SERMOUSE.SYS\n"
230    "fa860000 2bd4966f - kbdclass.SYS       fa870000 2bd49671 - MOUCLASS.SYS\n"
231    "fa880000 2bd9c0be - Videoprt.SYS       fa890000 2bd49638 - NCC1701E.SYS\n"
232    "fa8a0000 2bd4a4ce - Vga.SYS            fa8b0000 2bd496d0 - Msfs.SYS\n"
233    "fa8c0000 2bd496c3 - Npfs.SYS           fa8e0000 2bd496c9 - Ntfs.SYS\n"
234    "fa940000 2bd496df - NDIS.SYS           fa930000 2bd49707 - wdlan.sys\n"
235    "fa970000 2bd49712 - TDI.SYS            fa950000 2bd5a7fb - nbf.sys\n"
236    "fa980000 2bd72406 - streams.sys        fa9b0000 2bd4975f - ubnb.sys\n"
237    "fa9c0000 2bd5bfd7 - usbser.sys         fa9d0000 2bd4971d - netbios.sys\n"
238    "fa9e0000 2bd49678 - Parallel.sys       fa9f0000 2bd4969f - serial.SYS\n"
239    "faa00000 2bd49739 - mup.sys            faa40000 2bd4971f - SMBTRSUP.SYS\n"
240    "faa10000 2bd6f2a2 - srv.sys            faa50000 2bd4971a - afd.sys\n"
241    "faa60000 2bd6fd80 - rdr.sys            faaa0000 2bd49735 - bowser.sys\n"
242    "\n"
243    "Address dword dump Dll Base                                      - Name\n"
244    "801afc20 80106fc0 80106fc0 00000000 00000000 80149905 : "
245      "fa840000 - i8042prt.SYS\n"
246    "801afc24 80149905 80149905 ff8e6b8c 80129c2c ff8e6b94 : "
247      "8025c000 - SCSIPORT.SYS\n"
248    "801afc2c 80129c2c 80129c2c ff8e6b94 00000000 ff8e6b94 : "
249      "80100000 - ntoskrnl.exe\n"
250    "801afc34 801240f2 80124f02 ff8e6df4 ff8e6f60 ff8e6c58 : "
251      "80100000 - ntoskrnl.exe\n"
252    "801afc54 80124f16 80124f16 ff8e6f60 ff8e6c3c 8015ac7e : "
253      "80100000 - ntoskrnl.exe\n"
254    "801afc64 8015ac7e 8015ac7e ff8e6df4 ff8e6f60 ff8e6c58 : "
255      "80100000 - ntoskrnl.exe\n"
256    "801afc70 80129bda 80129bda 00000000 80088000 80106fc0 : "
257      "80100000 - ntoskrnl.exe\n"
258    "\n"
259    "Kernel Debugger Using: COM2 (Port 0x2f8, Baud Rate 19200)\n"
260    "Restart and set the recovery options in the system control panel\n"
261    "or the /CRASHDEBUG system start option. If this message reappears,\n"
262    "contact your system administrator or technical support group."
263      );
264
265   const char *w2ka =
266     ("*** STOP: 0x000000D1 (0xE1D38000,0x0000001C,0x00000000,0xF09D42DA)\n"
267      "DRIVER_IRQL_NOT_LESS_OR_EQUAL \n"
268      "\n"
269     "*** Address F09D42DA base at F09D4000, DateStamp 39f459ff - CRASHDD.SYS\n"
270      "\n"
271      "Beginning dump of physical memory\n");
272   const char *w2kb =
273     ("Physical memory dump complete. Contact your system administrator or\n"
274      "technical support group.\n");
275
276   if (which < 0 || which > 2) abort();
277
278   if (!get_boolean_resource((which == 0 ? "doWindows" :
279                              which == 1 ? "doNT" :
280                                           "doWin2K"),
281                             "DoWindows"))
282     return False;
283
284   XGetWindowAttributes (dpy, window, &xgwa);
285
286   fontname = get_string_resource ((xgwa.height > 600
287                                    ? (which == 0 ? "windows95.font2" :
288                                       which == 1 ? "windowsNT.font2" :
289                                                    "windows2K.font2")
290                                    : (which == 0 ? "windows95.font" :
291                                       which == 1 ? "windowsNT.font" :
292                                                    "windows2K.font")),
293                                   "Windows.Font");
294   if (!fontname || !*fontname) fontname = (char *)def_font;
295   font = XLoadQueryFont (dpy, fontname);
296   if (!font) font = XLoadQueryFont (dpy, def_font);
297   if (!font) exit(-1);
298   if (fontname && fontname != def_font)
299     free (fontname);
300
301   gcv.font = font->fid;
302   gcv.foreground = get_pixel_resource((which == 0 ? "windows95.foreground" :
303                                        which == 1 ? "windowsNT.foreground" :
304                                                     "windows2K.foreground"),
305                                       "Windows.Foreground",
306                                       dpy, xgwa.colormap);
307   gcv.background = get_pixel_resource((which == 0 ? "windows95.background" :
308                                        which == 1 ? "windowsNT.background" :
309                                                     "windows2K.background"),
310                                       "Windows.Background",
311                                       dpy, xgwa.colormap);
312   XSetWindowBackground(dpy, window, gcv.background);
313   XClearWindow(dpy, window);
314
315   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
316
317   if (which == 0)
318     draw_string(dpy, window, gc, &gcv, font,
319                 0, 0, xgwa.width, xgwa.height, w95, 0);
320   else if (which == 1)
321     draw_string(dpy, window, gc, &gcv, font, 0, 0, 10, 10, wnt, 750);
322   else
323     {
324       int line_height = font->ascent + font->descent + 1;
325       int x = 20;
326       int y = (xgwa.height / 4);
327
328       draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, w2ka, 750);
329       y += line_height * 6;
330       bsod_sleep(dpy, 4);
331       draw_string(dpy, window, gc, &gcv, font, x, y, 10, 10, w2kb, 750);
332     }
333
334   XFreeGC(dpy, gc);
335   XSync(dpy, False);
336   bsod_sleep(dpy, delay);
337   XClearWindow(dpy, window);
338   XFreeFont(dpy, font);
339   return True;
340 }
341
342 /* SCO OpenServer 5 panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
343  */
344 static Bool
345 sco (Display *dpy, Window window, int delay)
346 {
347   XGCValues gcv;
348   XWindowAttributes xgwa;
349   char *fontname;
350   const char *def_font = "fixed";
351   XFontStruct *font;
352   GC gc;
353   int lines_1 = 0, lines_2 = 0, lines_3 = 0, lines_4 = 0;
354   const char *s;
355
356   const char *sco_panic_1 =
357     ("Unexpected trap in kernel mode:\n"
358      "\n"
359      "cr0 0x80010013     cr2  0x00000014     cr3 0x00000000  tlb  0x00000000\n"
360      "ss  0x00071054    uesp  0x00012055     efl 0x00080888  ipl  0x00000005\n"
361      "cs  0x00092585     eip  0x00544a4b     err 0x004d4a47  trap 0x0000000E\n"
362      "eax 0x0045474b     ecx  0x0042544b     edx 0x57687920  ebx  0x61726520\n"
363      "esp 0x796f7520     ebp  0x72656164     esi 0x696e6720  edi  0x74686973\n"
364      "ds  0x3f000000     es   0x43494c48     fs  0x43525343  gs   0x4f4d4b53\n"
365      "\n"
366      "PANIC: k_trap - kernel mode trap type 0x0000000E\n"
367      "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n"
368     );
369   const char *sco_panic_2 =
370    ("...............................................................................\n"
371     );
372   const char *sco_panic_3 =
373     ("5023 pages dumped\n"
374      "\n"
375      "\n"
376      );
377   const char *sco_panic_4 =
378     ("**   Safe to Power Off   **\n"
379      "           - or -\n"
380      "** Press Any Key to Reboot **\n"
381     );
382
383   if (!get_boolean_resource("doSCO", "DoSCO"))
384     return False;
385
386   for (s = sco_panic_1; *s; s++) if (*s == '\n') lines_1++;
387   for (s = sco_panic_2; *s; s++) if (*s == '\n') lines_2++;
388   for (s = sco_panic_3; *s; s++) if (*s == '\n') lines_3++;
389   for (s = sco_panic_4; *s; s++) if (*s == '\n') lines_4++;
390
391   XGetWindowAttributes (dpy, window, &xgwa);
392
393   fontname = get_string_resource ((xgwa.height > 600
394                                    ? "sco.font2"
395                                    : "sco.font"),
396                                   "SCO.Font");
397   if (!fontname || !*fontname) fontname = (char *)def_font;
398   font = XLoadQueryFont (dpy, fontname);
399   if (!font) font = XLoadQueryFont (dpy, def_font);
400   if (!font) exit(-1);
401   if (fontname && fontname != def_font)
402     free (fontname);
403
404   gcv.font = font->fid;
405   gcv.foreground = get_pixel_resource(("sco.foreground"),
406                                       "SCO.Foreground",
407                                       dpy, xgwa.colormap);
408   gcv.background = get_pixel_resource(("sco.background"),
409                                       "SCO.Background",
410                                       dpy, xgwa.colormap);
411   XSetWindowBackground(dpy, window, gcv.background);
412   XClearWindow(dpy, window);
413
414   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
415
416   draw_string(dpy, window, gc, &gcv, font,
417               10, xgwa.height - ((lines_1 + lines_2 + lines_3 + lines_4 + 1) *
418                                  (font->ascent + font->descent + 1)),
419               10, 10,
420               sco_panic_1, 0);
421   XSync(dpy, False);
422   for (s = sco_panic_2; *s; s++)
423     {
424       char *ss = strdup(sco_panic_2);
425       ss[s - sco_panic_2] = 0;
426       draw_string(dpy, window, gc, &gcv, font,
427                   10, xgwa.height - ((lines_2 + lines_3 + lines_4 + 1) *
428                                      (font->ascent + font->descent + 1)),
429                   10, 10,
430                   ss, 0);
431       XSync(dpy, False);
432       free(ss);
433       if (bsod_sleep (dpy, -1))
434         goto DONE;
435     }
436
437   draw_string(dpy, window, gc, &gcv, font,
438               10, xgwa.height - ((lines_3 + lines_4 + 1) *
439                                  (font->ascent + font->descent + 1)),
440               10, 10,
441               sco_panic_3, 0);
442   XSync(dpy, False);
443   if (bsod_sleep(dpy, 1))
444     goto DONE;
445   draw_string(dpy, window, gc, &gcv, font,
446               10, xgwa.height - ((lines_4 + 1) *
447                                  (font->ascent + font->descent + 1)),
448               10, 10,
449               sco_panic_4, 0);
450   XSync(dpy, False);
451
452   bsod_sleep(dpy, delay);
453  DONE:
454   XClearWindow(dpy, window);
455   XFreeGC(dpy, gc);
456   XFreeFont(dpy, font);
457   return True;
458 }
459
460
461 /* Linux (sparc) panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
462  */
463 static Bool
464 sparc_linux (Display *dpy, Window window, int delay)
465 {
466   XGCValues gcv;
467   XWindowAttributes xgwa;
468   char *fontname;
469   const char *def_font = "fixed";
470   XFontStruct *font;
471   GC gc;
472   int lines = 1;
473   const char *s;
474
475   const char *linux_panic =
476     ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
477         "Unable to handle kernel paging request at virtual address f0d4a000\n"
478         "tsk->mm->context = 00000014\n"
479         "tsk->mm->pgd = f26b0000\n"
480         "              \\|/ ____ \\|/\n"
481         "              \"@'/ ,. \\`@\"\n"
482         "              /_| \\__/ |_\\\n"
483         "                 \\__U_/\n"
484         "gawk(22827): Oops\n"
485         "PSR: 044010c1 PC: f001c2cc NPC: f001c2d0 Y: 00000000\n"
486         "g0: 00001000 g1: fffffff7 g2: 04401086 g3: 0001eaa0\n"
487         "g4: 000207dc g5: f0130400 g6: f0d4a018 g7: 00000001\n"
488         "o0: 00000000 o1: f0d4a298 o2: 00000040 o3: f1380718\n"
489         "o4: f1380718 o5: 00000200 sp: f1b13f08 ret_pc: f001c2a0\n"
490         "l0: efffd880 l1: 00000001 l2: f0d4a230 l3: 00000014\n"
491         "l4: 0000ffff l5: f0131550 l6: f012c000 l7: f0130400\n"
492         "i0: f1b13fb0 i1: 00000001 i2: 00000002 i3: 0007c000\n"
493         "i4: f01457c0 i5: 00000004 i6: f1b13f70 i7: f0015360\n"
494         "Instruction DUMP:\n"
495     );
496
497   if (!get_boolean_resource("doSparcLinux", "DoSparcLinux"))
498     return False;
499
500   for (s = linux_panic; *s; s++) if (*s == '\n') lines++;
501
502   XGetWindowAttributes (dpy, window, &xgwa);
503
504   fontname = get_string_resource ((xgwa.height > 600
505                                    ? "sparclinux.font2"
506                                    : "sparclinux.font"),
507                                   "SparcLinux.Font");
508   if (!fontname || !*fontname) fontname = (char *)def_font;
509   font = XLoadQueryFont (dpy, fontname);
510   if (!font) font = XLoadQueryFont (dpy, def_font);
511   if (!font) exit(-1);
512   if (fontname && fontname != def_font)
513     free (fontname);
514
515   gcv.font = font->fid;
516   gcv.foreground = get_pixel_resource(("sparclinux.foreground"),
517                                       "SparcLinux.Foreground",
518                                       dpy, xgwa.colormap);
519   gcv.background = get_pixel_resource(("sparclinux.background"),
520                                       "SparcLinux.Background",
521                                       dpy, xgwa.colormap);
522   XSetWindowBackground(dpy, window, gcv.background);
523   XClearWindow(dpy, window);
524
525   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
526
527   draw_string(dpy, window, gc, &gcv, font,
528               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
529               10, 10,
530               linux_panic, 0);
531   XFreeGC(dpy, gc);
532   XSync(dpy, False);
533   bsod_sleep(dpy, delay);
534   XClearWindow(dpy, window);
535   XFreeFont(dpy, font);
536   return True;
537 }
538
539 /* BSD Panic by greywolf@starwolf.com - modeled after the Linux panic above.
540    By Grey Wolf <greywolf@siteROCK.com>
541  */
542 static Bool
543 bsd (Display *dpy, Window window, int delay)
544 {
545   XGCValues gcv;
546   XWindowAttributes xgwa;
547   char *fontname;
548   const char *def_font = "fixed";
549   XFontStruct *font;
550   GC gc;
551   int lines = 1;
552   int i, n, b;
553   const char *rbstr, *panicking;
554   char syncing[80], bbuf[5], *bp;
555
556   const char *panicstr[] =
557    {"panic: ifree: freeing free inode",
558     "panic: blkfree: freeing free block",
559     "panic: improbability coefficient below zero",
560     "panic: cgsixmmap",
561     "panic: crazy interrupts",
562     "panic: nmi",
563     "panic: attempted windows install",
564     "panic: don't",
565     "panic: free inode isn't",
566     "panic: cpu_fork: curproc",
567     "panic: malloc: out of space in kmem_map",
568     "panic: vogon starship detected",
569     "panic: teleport chamber: out of order",
570     "panic: Brain fried - core dumped"};
571      
572   if (!get_boolean_resource("doBSD", "DoBSD"))
573     return False;
574
575   for (i = 0; i < sizeof(syncing); i++)
576     syncing[i] = 0;
577
578   i = (random() & 0xffff) % (sizeof(panicstr) / sizeof(*panicstr));
579
580   panicking = panicstr[i];
581   strcpy(syncing, "Syncing disks: ");
582
583   b = (random() & 0xff) % 40;
584   for (n = 0; (n < 20) && (b > 0); n++)
585     {
586       if (i)
587         {
588           i = (random() & 0x7);
589           b -= (random() & 0xff) % 20;
590           if (b < 0)
591             b = 0;
592         }
593       sprintf (bbuf, "%d ", b);
594       strcat (syncing, bbuf);
595     }
596
597   if (b)
598     rbstr = "damn!";
599   else
600     rbstr = "sunk!";
601
602   lines = 5;
603
604   XGetWindowAttributes (dpy, window, &xgwa);
605
606   fontname = get_string_resource ((xgwa.height > 600
607                                    ? "bsd.font2"
608                                    : "bsd.font"),
609                                   "BSD.Font");
610   if (!fontname || !*fontname) fontname = (char *)def_font;
611   font = XLoadQueryFont (dpy, fontname);
612   if (!font) font = XLoadQueryFont (dpy, def_font);
613   if (!font) exit(-1);
614   if (fontname && fontname != def_font)
615     free (fontname);
616
617   gcv.font = font->fid;
618   gcv.foreground = get_pixel_resource(("bsd.foreground"),
619                                       "BSD.Foreground",
620                                       dpy, xgwa.colormap);
621   gcv.background = get_pixel_resource(("bsd.background"),
622                                       "BSD.Background",
623                                       dpy, xgwa.colormap);
624   XSetWindowBackground(dpy, window, gcv.background);
625   XClearWindow(dpy, window);
626
627   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
628
629   draw_string(dpy, window, gc, &gcv, font,
630               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
631               10, 10,
632               panicking, 0);
633   XSync(dpy, False);
634   lines--;
635
636   for (bp = syncing; *bp;)
637     {
638       char *bsd_bufs, oc = 0;
639       for (;*bp && (*bp != ' '); bp++)
640         ;
641       if (*bp == ' ')
642         {
643           oc = *bp;
644           *bp = 0;
645         }
646       bsd_bufs = strdup(syncing);
647       draw_string(dpy, window, gc, &gcv, font,
648                   10,
649                   xgwa.height - (lines * (font->ascent + font->descent + 1)),
650                   10, 10,
651                   bsd_bufs, 0);
652       XSync(dpy, False);
653       free(bsd_bufs);
654       if (oc)
655         *bp = oc;
656       if (bsod_sleep(dpy, -1))
657         goto DONE;
658       bp++;
659     }
660
661   lines--;
662   
663   draw_string(dpy, window, gc, &gcv, font,
664               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
665               10, 10,
666               rbstr, 0);
667   lines--;
668   draw_string(dpy, window, gc, &gcv, font,
669               10, xgwa.height - (lines * (font->ascent + font->descent + 1)),
670               10, 10,
671               "Rebooting", 0);
672
673   XFreeGC(dpy, gc);
674   XSync(dpy, False);
675   bsod_sleep(dpy, delay);
676
677 DONE:
678   XClearWindow(dpy, window);
679   XFreeFont(dpy, font);
680   return True;
681 }
682
683 static Bool
684 amiga (Display *dpy, Window window, int delay)
685 {
686   XGCValues gcv;
687   XWindowAttributes xgwa;
688   char *fontname;
689   const char *def_font = "fixed";
690   XFontStruct *font;
691   GC gc, gc2;
692   int height;
693   unsigned long fg, bg, bg2;
694   Pixmap pixmap = 0;
695   int pix_w = 0, pix_h = 0;
696   int string_width;
697   int margin;
698
699   const char *string =
700     ("_Software failure.  Press left mouse button to continue.\n"
701      "_Guru Meditation #00000003.00C01570");
702
703   if (!get_boolean_resource("doAmiga", "DoAmiga"))
704     return False;
705
706   XGetWindowAttributes (dpy, window, &xgwa);
707
708   fontname = get_string_resource ((xgwa.height > 600
709                                    ? "amiga.font2" : "amiga.font"),
710                                   "Amiga.Font");
711   if (!fontname || !*fontname) fontname = (char *)def_font;
712   font = XLoadQueryFont (dpy, fontname);
713   if (!font) font = XLoadQueryFont (dpy, def_font);
714   if (!font) exit(-1);
715   if (fontname && fontname != def_font)
716     free (fontname);
717
718   gcv.font = font->fid;
719   fg = gcv.foreground = get_pixel_resource("amiga.foreground",
720                                            "Amiga.Foreground",
721                                            dpy, xgwa.colormap);
722   bg = gcv.background = get_pixel_resource("amiga.background",
723                                            "Amiga.Background",
724                                            dpy, xgwa.colormap);
725   bg2 = get_pixel_resource("amiga.background2", "Amiga.Background",
726                            dpy, xgwa.colormap);
727   XSetWindowBackground(dpy, window, bg2);
728   XClearWindow(dpy, window);
729
730   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
731   gcv.background = fg; gcv.foreground = bg;
732   gc2 = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
733
734   height = (font->ascent + font->descent) * 6;
735
736 #if defined(HAVE_GDK_PIXBUF) || defined (HAVE_XPM)
737   pixmap = xpm_data_to_pixmap (dpy, window, (char **) amiga_hand,
738                                &pix_w, &pix_h, 0);
739 #endif /* HAVE_GDK_PIXBUF || HAVE_XPM */
740
741   if (pixmap && xgwa.height > 600)      /* scale up the bitmap */
742     {
743       pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
744                              pixmap, pix_w, pix_h);
745       pix_w *= 2;
746       pix_h *= 2;
747     }
748
749   if (pixmap)
750     {
751       int x = (xgwa.width - pix_w) / 2;
752       int y = ((xgwa.height - pix_h) / 2);
753       XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
754
755       XSync(dpy, False);
756       bsod_sleep(dpy, 2);
757
758       XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y + height);
759       XClearArea(dpy, window, 0, 0, xgwa.width, y + height, False);
760       XFreePixmap(dpy, pixmap);
761     }
762
763   XFillRectangle(dpy, window, gc2, 0, 0, xgwa.width, height);
764   margin = font->ascent;
765   string_width = draw_string(dpy, window, gc, &gcv, font,
766                              margin, 0,
767                              xgwa.width - (margin * 2), height,
768                              string, 0);
769   {
770     GC gca = gc;
771     while (delay > 0)
772       {
773         int x2;
774         XFillRectangle(dpy, window, gca, 0, 0, xgwa.width, margin);
775         XFillRectangle(dpy, window, gca, 0, 0, margin, height);
776         XFillRectangle(dpy, window, gca,
777                        0, height - margin, xgwa.width, margin);
778         x2 = margin + string_width;
779         if (x2 < xgwa.width - margin) x2 = xgwa.width - margin;
780         XFillRectangle(dpy, window, gca, x2, 0, margin, height);
781
782         gca = (gca == gc ? gc2 : gc);
783         XSync(dpy, False);
784         if (bsod_sleep(dpy, 1))
785           break;
786         delay--;
787       }
788   }
789
790   XFreeGC(dpy, gc);
791   XFreeGC(dpy, gc2);
792   XSync(dpy, False);
793   XClearWindow(dpy, window);
794   XFreeFont(dpy, font);
795   return True;
796 }
797
798
799 /* Atari ST, by Marcus Herbert <rhoenie@nobiscum.de>
800    Marcus had this to say:
801
802         Though I still have my Atari somewhere, I hardly remember
803         the meaning of the bombs. I think 9 bombs was "bus error" or
804         something like that.  And you often had a few bombs displayed
805         quickly and then the next few ones coming up step by step.
806         Perhaps somebody else can tell you more about it..  its just
807         a quick hack :-}
808  */
809 static Bool
810 atari (Display *dpy, Window window, int delay)
811 {
812         
813   XGCValues gcv;
814   XWindowAttributes xgwa;
815   const char *def_font = "fixed";
816   XFontStruct *font;
817   GC gc;
818   Pixmap pixmap = 0;
819   int pix_w = atari_width;
820   int pix_h = atari_height;
821   int offset;
822   int i, x, y;
823
824   if (!get_boolean_resource("doAtari", "DoAtari"))
825     return False;
826
827   XGetWindowAttributes (dpy, window, &xgwa);
828
829   font = XLoadQueryFont (dpy, def_font);
830   if (!font) exit(-1);
831                 
832   gcv.font = font->fid;
833   gcv.foreground = get_pixel_resource("atari.foreground", "Atari.Foreground",
834                                       dpy, xgwa.colormap);
835   gcv.background = get_pixel_resource("atari.background", "Atari.Background",
836                                       dpy, xgwa.colormap);
837
838   XSetWindowBackground(dpy, window, gcv.background);
839   XClearWindow(dpy, window);
840
841   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
842
843   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) atari_bits,
844                                        pix_w, pix_h,
845                                        gcv.foreground, gcv.background,
846                                        xgwa.depth);
847   pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
848                          pixmap, pix_w, pix_h);
849   pix_w *= 2;
850   pix_h *= 2;
851
852   offset = pix_w + 2;
853   x = 5;
854   y = (xgwa.height - (xgwa.height / 5));
855   if (y < 0) y = 0;
856
857   for (i=0 ; i<7 ; i++) {
858     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
859               (x + (i*offset)), y);
860   }  
861   
862   for (i=7 ; i<10 ; i++) {
863     if (bsod_sleep(dpy, 1))
864       goto DONE;
865     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h,
866               (x + (i*offset)), y);
867   }
868
869   bsod_sleep(dpy, delay);
870  DONE:
871   XFreePixmap(dpy, pixmap);
872   XFreeGC(dpy, gc);
873   XSync(dpy, False);
874   XClearWindow(dpy, window);
875   XFreeFont(dpy, font);
876   return True;
877 }
878
879
880 static Bool
881 mac (Display *dpy, Window window, int delay)
882 {
883   XGCValues gcv;
884   XWindowAttributes xgwa;
885   char *fontname;
886   const char *def_font = "fixed";
887   XFontStruct *font;
888   GC gc;
889   Pixmap pixmap = 0;
890   int pix_w = mac_width;
891   int pix_h = mac_height;
892   int offset = mac_height * 4;
893   int i;
894
895   const char *string = ("0 0 0 0 0 0 0 F\n"
896                         "0 0 0 0 0 0 0 3");
897
898   if (!get_boolean_resource("doMac", "DoMac"))
899     return False;
900
901   XGetWindowAttributes (dpy, window, &xgwa);
902
903   fontname = get_string_resource ("mac.font", "Mac.Font");
904   if (!fontname || !*fontname) fontname = (char *)def_font;
905   font = XLoadQueryFont (dpy, fontname);
906   if (!font) font = XLoadQueryFont (dpy, def_font);
907   if (!font) exit(-1);
908   if (fontname && fontname != def_font)
909     free (fontname);
910
911   gcv.font = font->fid;
912   gcv.foreground = get_pixel_resource("mac.foreground", "Mac.Foreground",
913                                       dpy, xgwa.colormap);
914   gcv.background = get_pixel_resource("mac.background", "Mac.Background",
915                                       dpy, xgwa.colormap);
916   XSetWindowBackground(dpy, window, gcv.background);
917   XClearWindow(dpy, window);
918
919   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
920
921   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits,
922                                        mac_width, mac_height,
923                                        gcv.foreground,
924                                        gcv.background,
925                                        xgwa.depth);
926
927   for(i = 0; i < 2; i++)
928     {
929       pixmap = double_pixmap(dpy, gc, xgwa.visual, xgwa.depth,
930                              pixmap, pix_w, pix_h);
931       pix_w *= 2; pix_h *= 2;
932     }
933
934   {
935     int x = (xgwa.width - pix_w) / 2;
936     int y = (((xgwa.height + offset) / 2) -
937              pix_h -
938              (font->ascent + font->descent) * 2);
939     if (y < 0) y = 0;
940     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
941     XFreePixmap(dpy, pixmap);
942   }
943
944   draw_string(dpy, window, gc, &gcv, font, 0, 0,
945               xgwa.width, xgwa.height + offset, string, 0);
946
947   XFreeGC(dpy, gc);
948   XSync(dpy, False);
949   bsod_sleep(dpy, delay);
950   XClearWindow(dpy, window);
951   XFreeFont(dpy, font);
952   return True;
953 }
954
955 static Bool
956 macsbug (Display *dpy, Window window, int delay)
957 {
958   XGCValues gcv;
959   XWindowAttributes xgwa;
960   char *fontname;
961   const char *def_font = "fixed";
962   XFontStruct *font;
963   GC gc, gc2;
964
965   int char_width, line_height;
966   int col_right, row_top, row_bottom, page_right, page_bottom, body_top;
967   int xoff, yoff;
968
969   const char *left = ("    SP     \n"
970                       " 04EB0A58  \n"
971                       "58 00010000\n"
972                       "5C 00010000\n"
973                       "   ........\n"
974                       "60 00000000\n"
975                       "64 000004EB\n"
976                       "   ........\n"
977                       "68 0000027F\n"
978                       "6C 2D980035\n"
979                       "   ....-..5\n"
980                       "70 00000054\n"
981                       "74 0173003E\n"
982                       "   ...T.s.>\n"
983                       "78 04EBDA76\n"
984                       "7C 04EBDA8E\n"
985                       "   .S.L.a.U\n"
986                       "80 00000000\n"
987                       "84 000004EB\n"
988                       "   ........\n"
989                       "88 00010000\n"
990                       "8C 00010000\n"
991                       "   ...{3..S\n"
992                       "\n"
993                       "\n"
994                       " CurApName \n"
995                       "  Finder   \n"
996                       "\n"
997                       " 32-bit VM \n"
998                       "SR Smxnzvc0\n"
999                       "D0 04EC0062\n"
1000                       "D1 00000053\n"
1001                       "D2 FFFF0100\n"
1002                       "D3 00010000\n"
1003                       "D4 00010000\n"
1004                       "D5 04EBDA76\n"
1005                       "D6 04EBDA8E\n"
1006                       "D7 00000001\n"
1007                       "\n"
1008                       "A0 04EBDA76\n"
1009                       "A1 04EBDA8E\n"
1010                       "A2 A0A00060\n"
1011                       "A3 027F2D98\n"
1012                       "A4 027F2E58\n"
1013                       "A5 04EC04F0\n"
1014                       "A6 04EB0A86\n"
1015                       "A7 04EB0A58");
1016   const char *bottom = ("  _A09D\n"
1017                         "     +00884    40843714     #$0700,SR         "
1018                         "                  ; A973        | A973\n"
1019                         "     +00886    40843765     *+$0400           "
1020                         "                                | 4A1F\n"
1021                         "     +00888    40843718     $0004(A7),([0,A7[)"
1022                         "                  ; 04E8D0AE    | 66B8");
1023
1024 #if 0
1025   const char *body = ("Bus Error at 4BF6D6CC\n"
1026                       "while reading word from 4BF6D6CC in User data space\n"
1027                       " Unable to access that address\n"
1028                       "  PC: 2A0DE3E6\n"
1029                       "  Frame Type: B008");
1030 #else
1031   const char * body = ("PowerPC unmapped memory exception at 003AFDAC "
1032                                                 "BowelsOfTheMemoryMgr+04F9C\n"
1033                       " Calling chain using A6/R1 links\n"
1034                       "  Back chain  ISA  Caller\n"
1035                       "  00000000    PPC  28C5353C  __start+00054\n"
1036                       "  24DB03C0    PPC  28B9258C  main+0039C\n"
1037                       "  24DB0350    PPC  28B9210C  MainEvent+00494\n"
1038                       "  24DB02B0    PPC  28B91B40  HandleEvent+00278\n"
1039                       "  24DB0250    PPC  28B83DAC  DoAppleEvent+00020\n"
1040                       "  24DB0210    PPC  FFD3E5D0  "
1041                                                 "AEProcessAppleEvent+00020\n"
1042                       "  24DB0132    68K  00589468\n"
1043                       "  24DAFF8C    68K  00589582\n"
1044                       "  24DAFF26    68K  00588F70\n"
1045                       "  24DAFEB3    PPC  00307098  "
1046                                                 "EmToNatEndMoveParams+00014\n"
1047                       "  24DAFE40    PPC  28B9D0B0  DoScript+001C4\n"
1048                       "  24DAFDD0    PPC  28B9C35C  RunScript+00390\n"
1049                       "  24DAFC60    PPC  28BA36D4  run_perl+000E0\n"
1050                       "  24DAFC10    PPC  28BC2904  perl_run+002CC\n"
1051                       "  24DAFA80    PPC  28C18490  Perl_runops+00068\n"
1052                       "  24DAFA30    PPC  28BE6CC0  Perl_pp_backtick+000FC\n"
1053                       "  24DAF9D0    PPC  28BA48B8  Perl_my_popen+00158\n"
1054                       "  24DAF980    PPC  28C5395C  sfclose+00378\n"
1055                       "  24DAF930    PPC  28BA568C  free+0000C\n"
1056                       "  24DAF8F0    PPC  28BA6254  pool_free+001D0\n"
1057                       "  24DAF8A0    PPC  FFD48F14  DisposePtr+00028\n"
1058                       "  24DAF7C9    PPC  00307098  "
1059                                                 "EmToNatEndMoveParams+00014\n"
1060                       "  24DAF780    PPC  003AA180  __DisposePtr+00010");
1061 #endif
1062
1063   const char *s;
1064   int body_lines = 1;
1065
1066   if (!get_boolean_resource("doMacsBug", "DoMacsBug"))
1067     return False;
1068
1069   for (s = body; *s; s++) if (*s == '\n') body_lines++;
1070
1071   XGetWindowAttributes (dpy, window, &xgwa);
1072
1073   fontname = get_string_resource ((xgwa.height > 850
1074                                    ? "macsbug.font3"
1075                                    : (xgwa.height > 700
1076                                       ? "macsbug.font2"
1077                                       : "macsbug.font")),
1078                                   "MacsBug.Font");
1079   if (!fontname || !*fontname) fontname = (char *)def_font;
1080   font = XLoadQueryFont (dpy, fontname);
1081   if (!font) font = XLoadQueryFont (dpy, def_font);
1082   if (!font) exit(-1);
1083   if (fontname && fontname != def_font)
1084     free (fontname);
1085
1086   gcv.font = font->fid;
1087   gcv.foreground = get_pixel_resource("macsbug.foreground",
1088                                       "MacsBug.Foreground",
1089                                       dpy, xgwa.colormap);
1090   gcv.background = get_pixel_resource("macsbug.background",
1091                                       "MacsBug.Background",
1092                                       dpy, xgwa.colormap);
1093
1094   gc = XCreateGC(dpy, window, GCFont|GCForeground|GCBackground, &gcv);
1095
1096   gcv.foreground = gcv.background;
1097   gc2 = XCreateGC(dpy, window, GCForeground, &gcv);
1098
1099   XSetWindowBackground(dpy, window,
1100                        get_pixel_resource("macsbug.borderColor",
1101                                           "MacsBug.BorderColor",
1102                                           dpy, xgwa.colormap));
1103   XClearWindow(dpy, window);
1104
1105   char_width = (font->per_char
1106                 ? font->per_char['n'-font->min_char_or_byte2].width
1107                 : font->min_bounds.width);
1108   line_height = font->ascent + font->descent + 1;
1109
1110   col_right = char_width * 12;
1111   page_bottom = line_height * 47;
1112
1113   if (page_bottom > xgwa.height) page_bottom = xgwa.height;
1114
1115   row_bottom = page_bottom - line_height;
1116   row_top = row_bottom - (line_height * 4);
1117   page_right = col_right + (char_width * 88);
1118   body_top = row_top - (line_height * body_lines);
1119
1120   page_bottom += 2;
1121   row_bottom += 2;
1122   body_top -= 4;
1123
1124   xoff = (xgwa.width - page_right) / 2;
1125   yoff = (xgwa.height - page_bottom) / 2;
1126   if (xoff < 0) xoff = 0;
1127   if (yoff < 0) yoff = 0;
1128
1129   XFillRectangle(dpy, window, gc2, xoff, yoff, page_right, page_bottom);
1130
1131   draw_string(dpy, window, gc, &gcv, font, xoff, yoff, 10, 10, left, 0);
1132   draw_string(dpy, window, gc, &gcv, font, xoff+col_right, yoff+row_top,
1133               10, 10, bottom, 0);
1134
1135   XFillRectangle(dpy, window, gc, xoff + col_right, yoff, 2, page_bottom);
1136   XDrawLine(dpy, window, gc,
1137             xoff+col_right, yoff+row_top, xoff+page_right, yoff+row_top);
1138   XDrawLine(dpy, window, gc,
1139             xoff+col_right, yoff+row_bottom, xoff+page_right, yoff+row_bottom);
1140   XDrawRectangle(dpy, window, gc,  xoff, yoff, page_right, page_bottom);
1141
1142   if (body_top > 4)
1143     body_top = 4;
1144
1145   draw_string(dpy, window, gc, &gcv, font,
1146               xoff + col_right + char_width, yoff + body_top, 10, 10, body,
1147               500);
1148
1149   while (delay > 0)
1150     {
1151       XDrawLine(dpy, window, gc,
1152                 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
1153                 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
1154       XSync(dpy, False);
1155       usleep(666666L);
1156       XDrawLine(dpy, window, gc2,
1157                 xoff+col_right+(char_width/2)+2, yoff+row_bottom+3,
1158                 xoff+col_right+(char_width/2)+2, yoff+page_bottom-3);
1159       XSync(dpy, False);
1160       usleep(333333L);
1161       if (bsod_sleep(dpy, 0))
1162         break;
1163       delay--;
1164     }
1165
1166   XFreeGC(dpy, gc);
1167   XFreeGC(dpy, gc2);
1168   XClearWindow(dpy, window);
1169   XFreeFont(dpy, font);
1170   return True;
1171 }
1172
1173 static Bool
1174 mac1 (Display *dpy, Window window, int delay)
1175 {
1176   XGCValues gcv;
1177   XWindowAttributes xgwa;
1178   GC gc;
1179   Pixmap pixmap = 0;
1180   int pix_w = macbomb_width;
1181   int pix_h = macbomb_height;
1182
1183   if (!get_boolean_resource("doMac1", "DoMac1"))
1184     return False;
1185
1186   XGetWindowAttributes (dpy, window, &xgwa);
1187
1188   gcv.foreground = get_pixel_resource("mac1.foreground", "Mac.Foreground",
1189                                       dpy, xgwa.colormap);
1190   gcv.background = get_pixel_resource("mac1.background", "Mac.Background",
1191                                       dpy, xgwa.colormap);
1192   XSetWindowBackground(dpy, window, gcv.background);
1193   XClearWindow(dpy, window);
1194
1195   gc = XCreateGC(dpy, window, GCForeground|GCBackground, &gcv);
1196
1197   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) macbomb_bits,
1198                                        macbomb_width, macbomb_height,
1199                                        gcv.foreground,
1200                                        gcv.background,
1201                                        xgwa.depth);
1202
1203   {
1204     int x = (xgwa.width - pix_w) / 2;
1205     int y = (xgwa.height - pix_h) / 2;
1206     if (y < 0) y = 0;
1207     XFillRectangle (dpy, window, gc, 0, 0, xgwa.width, xgwa.height);
1208     XSync(dpy, False);
1209     if (bsod_sleep(dpy, 1))
1210       goto DONE;
1211     XCopyArea(dpy, pixmap, window, gc, 0, 0, pix_w, pix_h, x, y);
1212   }
1213
1214  DONE:
1215   XFreeGC(dpy, gc);
1216   XFreePixmap(dpy, pixmap);
1217   XSync(dpy, False);
1218   bsod_sleep(dpy, delay);
1219   XClearWindow(dpy, window);
1220   return True;
1221 }
1222
1223
1224
1225
1226 \f
1227 /* blit damage
1228  *
1229  * by Martin Pool <mbp@samba.org>, Feb 2000.
1230  *
1231  * This is meant to look like the preferred failure mode of NCD
1232  * Xterms.  The parameters for choosing what to copy where might not
1233  * be quite right, but it looks about ugly enough.
1234  */
1235 static Bool
1236 blitdamage (Display *dpy, Window window, int delay)
1237 {
1238   XGCValues gcv;
1239   XWindowAttributes xwa;
1240   GC gc0;
1241   int i;
1242   int delta_x = 0, delta_y = 0;
1243   int w, h;
1244   int chunk_h, chunk_w;
1245   int steps;
1246   long gc_mask = 0;
1247   int src_x, src_y;
1248   int x, y;
1249   
1250   if (!get_boolean_resource("doBlitDamage", "DoBlitDamage"))
1251     return False;
1252
1253   XGetWindowAttributes(dpy, window, &xwa);
1254
1255   grab_screen_image(xwa.screen, window);
1256
1257   w = xwa.width;
1258   h = xwa.height;
1259
1260   gc_mask = GCForeground;
1261   
1262   gcv.plane_mask = random();
1263   gc_mask |= GCPlaneMask;
1264   
1265   gc0 = XCreateGC(dpy, window, gc_mask, &gcv);
1266
1267   steps = 50;
1268   chunk_w = w / (random() % 1 + 1);
1269   chunk_h = h / (random() % 1 + 1);
1270   if (random() & 0x1000) 
1271     delta_y = random() % 600;
1272   if (!delta_y || (random() & 0x2000))
1273     delta_x = random() % 600;
1274   src_x = 0; 
1275   src_y = 0; 
1276   x = 0;
1277   y = 0;
1278   
1279   for (i = 0; i < steps; i++) {
1280     if (x + chunk_w > w) 
1281       x -= w;
1282     else
1283       x += delta_x;
1284     
1285     if (y + chunk_h > h)
1286       y -= h;
1287     else
1288       y += delta_y;
1289     
1290     XCopyArea(dpy, window, window, gc0,
1291               src_x, src_y, 
1292               chunk_w, chunk_h,
1293               x, y);
1294
1295     if (bsod_sleep(dpy, 0))
1296       goto DONE;
1297   }
1298
1299   bsod_sleep(dpy, delay);
1300
1301  DONE:
1302   XFreeGC(dpy, gc0);
1303
1304   return True;
1305 }
1306
1307 \f
1308 /*
1309  * SPARC Solaris panic. Should look pretty authentic on Solaris boxes.
1310  * Anton Solovyev <solovam@earthlink.net>
1311  */ 
1312
1313 static int solaris_max_scroll = 10;
1314
1315 typedef struct
1316 {
1317   Display *dpy;
1318   Window window;
1319   GC gc;
1320   Pixmap subwindow;             /* The text subwindow */
1321   XFontStruct *xfs;
1322   int width;                    /* Window width in pixels */
1323   int height;                   /* Window height in pixels */
1324   int sub_width;                /* Text subwindow width in pixels */
1325   int sub_height;               /* Text subwindow height in pixels */
1326   int sub_x;                    /* upper left corner of the text subwindow */
1327   int sub_y;                    /* upper left corner of the text subwindow */
1328   int char_width;               /* Char width in pixels */
1329   int line_height;              /* Line height in pixels */
1330   int columns;                  /* Number of columns in the text screen */
1331   int lines;                    /* Number of lines in the text screen */
1332   int x;                        /* position of the cursor */
1333   int y;                        /* position of the cursor */
1334 } solaris_console;
1335
1336
1337 static solaris_console *
1338 make_solaris_console (Display *dpy, Window window)
1339 {
1340   const char *def_font = "fixed";
1341   solaris_console* ts;
1342
1343   XWindowAttributes xgwa;
1344   XGCValues gcv;
1345   char* fontname;
1346
1347   ts = malloc(sizeof(solaris_console));
1348
1349   ts->window = window;
1350   ts->dpy = dpy;
1351
1352   ts->x = 0;
1353   ts->y = 0;
1354
1355   XGetWindowAttributes (dpy, window, &xgwa);
1356   ts->width = xgwa.width;
1357   ts->height = xgwa.height;
1358   ts->sub_width = ts->width * 0.8;
1359   ts->sub_height = ts->height * 0.8;
1360
1361   fontname = get_string_resource ("solaris.font", "Solaris.Font");
1362   ts->xfs = XLoadQueryFont (dpy, fontname);
1363   if (!ts->xfs)
1364     {
1365       fontname = get_string_resource("solaris.font2", "Solaris.Font");
1366       ts->xfs = XLoadQueryFont(dpy, fontname);
1367     }
1368   if (!ts->xfs)
1369     ts->xfs = XLoadQueryFont(dpy, def_font);
1370   if (!ts->xfs)
1371     {
1372       fprintf (stderr, "Can't load font\n");
1373       XFreeFont (dpy, ts->xfs);
1374       free (ts);
1375       exit (1);
1376     }
1377   gcv.font = ts->xfs->fid;
1378   ts->char_width = (ts->xfs->per_char
1379                     ? ts->xfs->per_char[ts->xfs->min_char_or_byte2 +
1380                                        ts->xfs->default_char].width
1381                     : ts->xfs->max_bounds.width);
1382   ts->line_height = ts->xfs->ascent + ts->xfs->descent + 1;
1383
1384   ts->columns = ts->sub_width / ts->char_width;
1385   ts->lines = ts->sub_height / ts->line_height;
1386
1387   ts->sub_x = (ts->width - ts->sub_width) / 2;
1388   ts->sub_y = (ts->height - ts->sub_height) / 2;
1389
1390   ts->subwindow = XCreatePixmap (dpy, window, ts->sub_width,
1391                                  ts->sub_height * (solaris_max_scroll + 1),
1392                                  xgwa.depth);
1393   grab_screen_image (xgwa.screen, window);
1394   gcv.function = GXcopy;
1395   gcv.background = XBlackPixel (dpy, XDefaultScreen(dpy));
1396   gcv.foreground = XWhitePixel (dpy, XDefaultScreen(dpy));
1397   ts->gc = XCreateGC (dpy, window,
1398                       GCFunction | GCBackground | GCForeground | GCFont,
1399                       &gcv);
1400   XCopyArea (dpy, window, ts->subwindow, ts->gc,
1401              ts->sub_x, ts->sub_y, ts->sub_width, ts->sub_height,
1402              0, 0);
1403   XFillRectangle (dpy, ts->subwindow, ts->gc, 0, ts->sub_height,
1404                   ts->sub_width, ts->sub_height * solaris_max_scroll);
1405
1406   gcv.background = XWhitePixel (dpy, XDefaultScreen (dpy));
1407   gcv.foreground = XBlackPixel (dpy, XDefaultScreen (dpy));
1408   XChangeGC (dpy, ts->gc, GCBackground | GCForeground, &gcv);
1409
1410   return(ts);
1411 }
1412
1413 static void
1414 free_solaris_console (solaris_console* ts)
1415 {
1416   XFreePixmap (ts->dpy, ts->subwindow);
1417   XFreeGC (ts->dpy, ts->gc);
1418   XFreeFont (ts->dpy, ts->xfs);
1419   free (ts);
1420 }
1421
1422 static void
1423 solaris_draw (solaris_console* ts)
1424 {
1425   XCopyArea (ts->dpy, ts->subwindow, ts->window, ts->gc, 0,
1426              (ts->y + 1) * ts->line_height, ts->sub_width,
1427              ts->sub_height, ts->sub_x, ts->sub_y);
1428 }
1429
1430 static void
1431 solaris_putc (solaris_console* ts, const char aChar)
1432 {
1433   if (ts->y >= solaris_max_scroll * ts->lines)
1434     return;
1435
1436   if (!ts->y && !ts->x)
1437     solaris_draw (ts);
1438
1439   switch (aChar)
1440     {
1441     case '\n':
1442       ts->y++;
1443       ts->x = 0;
1444       solaris_draw (ts);
1445       break;
1446     case '\b':
1447       if(ts->x > 0)
1448         ts->x--;
1449       break;
1450     default:
1451       XDrawImageString (ts->dpy, ts->subwindow, ts->gc,
1452                         (ts->x * ts->char_width -
1453                          ts->xfs->min_bounds.lbearing),
1454                         (ts->sub_height + (ts->y + 1) *
1455                          ts->line_height - ts->xfs->descent),
1456                         &aChar, 1);
1457       XCopyArea (ts->dpy, ts->subwindow, ts->window, ts->gc,
1458                  ts->x * ts->char_width,
1459                  ts->y * ts->line_height + ts->sub_height,
1460                  ts->xfs->max_bounds.rbearing - ts->xfs->min_bounds.lbearing,
1461                  ts->line_height, ts->sub_x + ts->x * ts->char_width,
1462                  ts->sub_y + ts->sub_height - ts->line_height);
1463       ts->x++;
1464       if (ts->x >= ts->columns)
1465         {
1466           ts->x = 0;
1467           solaris_putc(ts, '\n');
1468         }
1469       break;
1470     }
1471 }
1472
1473 static void
1474 solaris_puts (solaris_console* ts, const char* aString, int delay)
1475 {
1476   const char *c;
1477   for (c = aString; *c; ++c)
1478     {
1479       solaris_putc (ts, *c);
1480       if (delay)
1481         {
1482           XSync(ts->dpy, 0);
1483           usleep(delay);
1484         }
1485     }
1486   XSync (ts->dpy, 0);
1487 }
1488
1489 static Bool
1490 sparc_solaris (Display* dpy, Window window, int delay)
1491 {
1492   const char *msg1 =
1493     "BAD TRAP: cpu=0 type=0x31 rp=0x2a10043b5e0 addr=0xf3880 mmu_fsr=0x0\n"
1494     "BAD TRAP occured in module \"unix\" due to an illegal access to a"
1495     " user address.\n"
1496     "adb: trap type = 0x31\n"
1497     "addr=0xf3880\n"
1498     "pid=307, pc=0x100306e4, sp=0x2a10043ae81, tstate=0x4480001602,"
1499     " context=0x87f\n"
1500     "g1-g7: 1045b000, 32f, 10079440, 180, 300000ebde8, 0, 30000953a20\n"
1501     "Begin traceback... sp = 2a10043ae81\n"
1502     "Called from 100bd060, fp=2a10043af31, args=f3700 300008cc988 f3880 0"
1503     " 1 300000ebde0.\n"
1504     "Called from 101fe1bc, fp=2a10043b011, args=3000045a240 104465a0"
1505     " 300008e47d0 300008e48fa 300008ae350 300008ae410\n"
1506     "Called from 1007c520, fp=2a10043b0c1, args=300008e4878 300003596e8 0"
1507     " 3000045a320 0 3000045a220\n"
1508     "Called from 1007c498, fp=2a10043b171, args=1045a000 300007847f0 20"
1509     " 3000045a240 1 0\n"
1510     "Called from 1007972c, fp=2a10043b221, args=1 300009517c0 30000951e58 1"
1511     " 300007847f0 0\n"
1512     "Called from 10031e10, fp=2a10043b2d1, args=3000095b0c8 0 300009396a8"
1513     " 30000953a20 0 1\n"
1514     "Called from 10000bdd8, fp=ffffffff7ffff1c1, args=0 57 100131480"
1515     " 100131480 10012a6e0 0\n"
1516     "End traceback...\n"
1517     "panic[cpu0]/thread=30000953a20: trap\n"
1518     "syncing file systems...";
1519   const char *msg2 =
1520     " 1 done\n"
1521     "dumping to /dev/dsk/c0t0d0s3, offset 26935296\n";
1522   const char *msg3 =
1523     ": 2803 pages dumped, compression ratio 2.88, dump succeeded\n";
1524   const char *msg4 =
1525     "rebooting...\n"
1526     "Resetting ...";
1527
1528   solaris_console* ts;
1529   int i;
1530   char buf[256];
1531
1532   if (!get_boolean_resource("doSolaris", "DoSolaris"))
1533     return False;
1534
1535   ts = make_solaris_console (dpy, window);
1536
1537   solaris_puts (ts, msg1, 0);
1538   if (bsod_sleep (dpy, 3))
1539     goto DONE;
1540
1541   solaris_puts (ts, msg2, 0);
1542   if (bsod_sleep (dpy, 2))
1543     goto DONE;
1544
1545   for (i = 1; i <= 100; ++i)
1546     {
1547       sprintf(buf, "\b\b\b\b\b\b\b\b\b\b\b%3d%% done", i);
1548       solaris_puts(ts, buf, 0);
1549       if (bsod_sleep (dpy, -1))
1550         goto DONE;
1551     }
1552
1553   solaris_puts (ts, msg3, 0);
1554   if (bsod_sleep (dpy, 2))
1555     goto DONE;
1556
1557   solaris_puts (ts, msg4, 0);
1558   if (bsod_sleep(dpy, 3))
1559     goto DONE;
1560
1561   XFillRectangle (ts->dpy, ts->window, ts->gc, 0, 0,
1562                   ts->width, ts->height);
1563
1564   bsod_sleep (dpy, 3);
1565
1566  DONE:
1567   free_solaris_console (ts);
1568
1569   return True;
1570 }
1571
1572 \f
1573 char *progclass = "BSOD";
1574
1575 char *defaults [] = {
1576   "*delay:                 30",
1577
1578   "*doWindows:             True",
1579   "*doNT:                  True",
1580   "*doWin2K:               True",
1581   "*doAmiga:               True",
1582   "*doMac:                 True",
1583   "*doMacsBug:             True",
1584   "*doMac1:                True",
1585   "*doSCO:                 True",
1586   "*doAtari:               False",      /* boring */
1587   "*doBSD:                 False",      /* boring */
1588   "*doSparcLinux:          False",      /* boring */
1589   "*doBlitDamage:          True",
1590   "*doSolaris:             True",
1591
1592   ".Windows.font:          -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1593   ".Windows.font2:         -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
1594   ".Windows.foreground:    White",
1595   ".Windows.background:    Blue",
1596
1597   ".Amiga.font:            -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1598   ".Amiga.font2:           -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
1599   ".Amiga.foreground:      Red",
1600   ".Amiga.background:      Black",
1601   ".Amiga.background2:     White",
1602
1603   ".Mac.font:              -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1604   ".Mac.foreground:        PaleTurquoise1",
1605   ".Mac.background:        Black",
1606
1607   ".Atari.foreground:      Black",
1608   ".Atari.background:      White",
1609
1610   ".MacsBug.font:          -*-courier-medium-r-*-*-*-100-*-*-m-*-*-*",
1611   ".MacsBug.font2:         -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1612   ".MacsBug.font3:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
1613   ".MacsBug.foreground:    Black",
1614   ".MacsBug.background:    White",
1615   ".MacsBug.borderColor:   #AAAAAA",
1616
1617   ".mac1.foreground:       Black",
1618   ".mac1.background:       White",
1619
1620   ".SCO.font:              -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1621   ".SCO.font2:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
1622   ".SCO.foreground:        White",
1623   ".SCO.background:        Black",
1624
1625   ".SparcLinux.font:       -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1626   ".SparcLinux.font2:      -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
1627   ".SparcLinux.foreground: White",
1628   ".SparcLinux.background: Black",
1629
1630   ".BSD.font:               vga",
1631   ".BSD.font:               -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
1632   ".BSD.font2:              -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
1633 /* ".BSD.font2:             -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*", */
1634   ".BSD.foreground:         #c0c0c0",
1635   ".BSD.background:         Black",
1636
1637   ".Solaris.font:           -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
1638   ".Solaris.font2:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
1639   "*dontClearRoot:          True",
1640   0
1641 };
1642
1643 XrmOptionDescRec options [] = {
1644   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
1645   { "-windows",         ".doWindows",           XrmoptionNoArg,  "True"  },
1646   { "-no-windows",      ".doWindows",           XrmoptionNoArg,  "False" },
1647   { "-nt",              ".doNT",                XrmoptionNoArg,  "True"  },
1648   { "-no-nt",           ".doNT",                XrmoptionNoArg,  "False" },
1649   { "-2k",              ".doWin2K",             XrmoptionNoArg,  "True"  },
1650   { "-no-2k",           ".doWin2K",             XrmoptionNoArg,  "False" },
1651   { "-amiga",           ".doAmiga",             XrmoptionNoArg,  "True"  },
1652   { "-no-amiga",        ".doAmiga",             XrmoptionNoArg,  "False" },
1653   { "-mac",             ".doMac",               XrmoptionNoArg,  "True"  },
1654   { "-no-mac",          ".doMac",               XrmoptionNoArg,  "False" },
1655   { "-atari",           ".doAtari",             XrmoptionNoArg,  "True"  },
1656   { "-no-atari",        ".doAtari",             XrmoptionNoArg,  "False" },
1657   { "-macsbug",         ".doMacsBug",           XrmoptionNoArg,  "True"  },
1658   { "-no-macsbug",      ".doMacsBug",           XrmoptionNoArg,  "False" },
1659   { "-sco",             ".doSCO",               XrmoptionNoArg,  "True"  },
1660   { "-no-sco",          ".doSCO",               XrmoptionNoArg,  "False" },
1661   { "-bsd",             ".doBSD",               XrmoptionNoArg,  "True"  },
1662   { "-no-bsd",          ".doBSD",               XrmoptionNoArg,  "False" },
1663   { "-sparclinux",      ".doSparcLinux",        XrmoptionNoArg,  "True"  },
1664   { "-no-sparclinux",   ".doSparcLinux",        XrmoptionNoArg,  "False" },
1665   { "-blitdamage",      ".doBlitDamage",        XrmoptionNoArg,  "True"  },
1666   { "-no-blitdamage",   ".doBlitDamage",        XrmoptionNoArg,  "False" },
1667   { "-solaris",         ".doSolaris",           XrmoptionNoArg,  "True"  },
1668   { "-no-solaris",      ".doSolaris",           XrmoptionNoArg,  "False" },
1669   { 0, 0, 0, 0 }
1670 };
1671
1672
1673 void
1674 screenhack (Display *dpy, Window window)
1675 {
1676   int loop = 0;
1677   int i = -1;
1678   int j = -1;
1679   int delay = get_integer_resource ("delay", "Integer");
1680   if (delay < 3) delay = 3;
1681
1682   if (!get_boolean_resource ("root", "Boolean"))
1683     {
1684       XWindowAttributes xgwa;
1685       XGetWindowAttributes (dpy, window, &xgwa);
1686       XSelectInput (dpy, window,
1687                     xgwa.your_event_mask | KeyPressMask | ButtonPressMask);
1688     }
1689
1690   while (1)
1691     {
1692       Bool did;
1693       do {  i = (random() & 0xFF) % 13; } while (i == j);
1694       switch (i)
1695         {
1696         case 0: did = windows(dpy, window, delay, 0); break;
1697         case 1: did = windows(dpy, window, delay, 1); break;
1698         case 2: did = windows(dpy, window, delay, 2); break;
1699         case 3: did = amiga(dpy, window, delay); break;
1700         case 4: did = mac(dpy, window, delay); break;
1701         case 5: did = macsbug(dpy, window, delay); break;
1702         case 6: did = mac1(dpy, window, delay); break;
1703         case 7: did = sco(dpy, window, delay); break;
1704         case 8: did = sparc_linux(dpy, window, delay); break;
1705         case 9: did = bsd(dpy, window, delay); break;
1706         case 10: did = atari(dpy, window, delay); break;
1707         case 11: did = blitdamage(dpy, window, delay); break;
1708         case 12: did = sparc_solaris(dpy, window, delay); break;
1709         default: abort(); break;
1710         }
1711       loop++;
1712       if (loop > 100) j = -1;
1713       if (loop > 200)
1714         {
1715           fprintf (stderr, "%s: no display modes enabled?\n", progname);
1716           exit(-1);
1717         }
1718       if (!did) continue;
1719       XSync (dpy, False);
1720       j = i;
1721       loop = 0;
1722     }
1723 }