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