824a924128cd41b2831ea787768cd3b9d4adb192
[xscreensaver] / hacks / bsod.c
1 /* xscreensaver, Copyright (c) 1998-2013 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  * Mostly rewritten by jwz, 20-Feb-2006.
15  */
16
17
18 /* To add a new mode:
19
20     - Define a function `new_os(dpy,win)' that returns a `bsod_state' struct.
21     - Draw on the window to set up its frame-zero state.  This must be fast:
22       no sleeping or long loops!
23     - Populate the bsod_state structure with additional actions to take by
24       using the various BSOD_ macros.  Note that you can control the delays
25       when printing text on a per-character or per-line basis.
26     - Insert your function in the `all_modes' table.
27     - Add a `doXXX' entry to `bsod_defaults'.
28     - Add fonts or colors to `bsod_defaults' if necessary.
29
30    Look at windows_31() for a simple example.
31
32    Look at linux_fsck() for a more complicated example with random behavior.
33
34    Or, you can bypass all that: look at nvidia() for a really hairy example.
35  */
36
37
38 #include "screenhack.h"
39 #include "xpm-pixmap.h"
40 #include "apple2.h"
41
42 #include <ctype.h>
43
44 #ifdef HAVE_XSHM_EXTENSION
45 #include "xshm.h"
46 #endif
47
48 #ifdef HAVE_UNAME
49 # include <sys/utsname.h>
50 #endif /* HAVE_UNAME */
51
52 #if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) || defined(HAVE_COCOA)
53 # define DO_XPM
54 #endif
55
56 #ifdef DO_XPM
57 # include "images/amiga.xpm"
58 # include "images/hmac.xpm"
59 # include "images/osx_10_2.xpm"
60 # include "images/osx_10_3.xpm"
61 #endif
62 #include "images/atari.xbm"
63 #include "images/mac.xbm"
64 #include "images/macbomb.xbm"
65 #include "images/atm.xbm"
66
67 #undef countof
68 #define countof(x) (sizeof((x))/sizeof((*x)))
69
70 #undef EOF
71 typedef enum { EOF=0, 
72                LEFT, CENTER, RIGHT, 
73                LEFT_FULL, CENTER_FULL, RIGHT_FULL, 
74                COLOR, INVERT, MOVETO, MARGINS,
75                CURSOR_BLOCK, CURSOR_LINE, RECT, COPY, PIXMAP, IMG,
76                PAUSE, CHAR_DELAY, LINE_DELAY,
77                LOOP, RESET
78 } bsod_event_type;
79
80 struct bsod_event {
81   bsod_event_type type;
82   void *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
83 };
84
85 struct bsod_state {
86   Display *dpy;
87   Window window;
88   XWindowAttributes xgwa;
89   XFontStruct *font;
90   unsigned long fg, bg;
91   GC gc;
92   int left_margin, right_margin;        /* for text wrapping */
93   int top_margin, bottom_margin;        /* for text scrolling */
94   Bool wrap_p;
95   Bool scroll_p;
96
97   Pixmap pixmap;                /* Source image used by BSOD_PIXMAP */
98
99   int x, y;                     /* current text-drawing position */
100   int current_left;             /* don't use this */
101
102   int pos;                      /* position in queue */
103   int queue_size;
104   struct bsod_event *queue;
105
106   unsigned long char_delay;     /* delay between printing characters */
107   unsigned long line_delay;     /* delay between printing lines */
108
109   Bool macx_eol_kludge;
110
111   void *closure;
112   int  (*draw_cb) (struct bsod_state *);
113   void (*free_cb) (struct bsod_state *);
114
115   async_load_state *img_loader;
116 };
117
118
119 # if !defined(__GNUC__) && !defined(__extension__)
120   /* don't warn about "string length is greater than the length ISO C89
121      compilers are required to support" in these string constants... */
122 #  define  __extension__ /**/
123 # endif
124
125
126 /* Draw text at the current position; align is LEFT, CENTER, RIGHT, or *_FULL
127    (meaning to clear the whole line margin to margin).
128  */
129 #define BSOD_TEXT(bst,align,string) do { \
130   ensure_queue (bst); \
131   (bst)->queue[(bst)->pos].type = (align); \
132   (bst)->queue[(bst)->pos].arg1 = (void *) strdup (__extension__ (string)); \
133   (bst)->queue[(bst)->pos].arg2 = (bst)->queue[(bst)->pos].arg1; \
134   (bst)->queue[(bst)->pos].arg3 = (void *) 0; \
135   (bst)->pos++; \
136   } while (0)
137
138 /* Flip the foreground and background colors
139  */
140 #define BSOD_INVERT(bst) do { \
141   ensure_queue (bst); \
142   (bst)->queue[(bst)->pos].type = INVERT; \
143   (bst)->pos++; \
144   } while (0)
145
146 /* Set the foreground and background colors to the given pixels
147  */
148 #define BSOD_COLOR(bst,fg,bg) do { \
149   ensure_queue (bst); \
150   (bst)->queue[(bst)->pos].type = COLOR; \
151   (bst)->queue[(bst)->pos].arg1 = (void *) fg; \
152   (bst)->queue[(bst)->pos].arg2 = (void *) bg; \
153   (bst)->pos++; \
154   } while (0)
155
156 /* Set the position of the next text.
157    Note that this is the baseline: lower left corner of next char printed.
158  */
159 #define BSOD_MOVETO(bst,x,y) do { \
160   ensure_queue (bst); \
161   (bst)->queue[(bst)->pos].type = MOVETO; \
162   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (x)); \
163   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (y)); \
164   (bst)->pos++; \
165   } while (0)
166
167 /* Delay for at least the given number of microseconds.
168  */
169 #define BSOD_PAUSE(bst,usec) do { \
170   ensure_queue (bst); \
171   (bst)->queue[(bst)->pos].type = PAUSE; \
172   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (usec)); \
173   (bst)->pos++; \
174   } while (0)
175
176 /* Set the delay after each character is printed.
177  */
178 #define BSOD_CHAR_DELAY(bst,usec) do { \
179   ensure_queue (bst); \
180   (bst)->queue[(bst)->pos].type = CHAR_DELAY; \
181   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (usec)); \
182   (bst)->pos++; \
183   } while (0)
184
185 /* Set the delay after each newline.
186  */
187 #define BSOD_LINE_DELAY(bst,usec) do { \
188   ensure_queue (bst); \
189   (bst)->queue[(bst)->pos].type = LINE_DELAY; \
190   (bst)->queue[(bst)->pos].arg1 = (void *) (usec); \
191   (bst)->pos++; \
192   } while (0)
193
194 /* Set the prevailing left/right margins (used when strings have
195    embedded newlines, and when centering or right-justifying text.)
196  */
197 #define BSOD_MARGINS(bst,left,right) do { \
198   ensure_queue (bst); \
199   (bst)->queue[(bst)->pos].type = MARGINS; \
200   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (left)); \
201   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (right)); \
202   (bst)->pos++; \
203   } while (0)
204
205 /* Draw a blinking cursor; type is CURSOR_BLOCK or CURSOR_LINE.
206    usec is how long 1/2 of a cycle is.  count is how many times to blink.
207    (You can pass a gigantic number if this is the last thing in your mode.)
208  */
209 #define BSOD_CURSOR(bst,ctype,usec,count) do { \
210   ensure_queue (bst); \
211   (bst)->queue[(bst)->pos].type = (ctype); \
212   (bst)->queue[(bst)->pos].arg1 = (void *) (usec); \
213   (bst)->queue[(bst)->pos].arg2 = (void *) (count); \
214   (bst)->pos++; \
215   } while (0)
216
217 /* Draw or fill a rectangle.  You can set line-width in the GC.
218  */
219 #define BSOD_RECT(bst,fill,x,y,w,h) do { \
220   ensure_queue (bst); \
221   (bst)->queue[(bst)->pos].type = RECT; \
222   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (fill)); \
223   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (x)); \
224   (bst)->queue[(bst)->pos].arg3 = (void *) ((long) (y)); \
225   (bst)->queue[(bst)->pos].arg4 = (void *) ((long) (w)); \
226   (bst)->queue[(bst)->pos].arg5 = (void *) ((long) (h)); \
227   (bst)->pos++; \
228   } while (0)
229
230 /* Copy a rect from the window, to the window.
231  */
232 #define BSOD_COPY(bst,srcx,srcy,w,h,tox,toy) do { \
233   ensure_queue (bst); \
234   (bst)->queue[(bst)->pos].type = COPY; \
235   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (srcx)); \
236   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (srcy)); \
237   (bst)->queue[(bst)->pos].arg3 = (void *) ((long) (w)); \
238   (bst)->queue[(bst)->pos].arg4 = (void *) ((long) (h)); \
239   (bst)->queue[(bst)->pos].arg5 = (void *) ((long) (tox)); \
240   (bst)->queue[(bst)->pos].arg6 = (void *) ((long) (toy)); \
241   (bst)->pos++; \
242   } while (0)
243
244 /* Copy a rect from bst->pixmap to the window.
245  */
246 #define BSOD_PIXMAP(bst,srcx,srcy,w,h,tox,toy) do { \
247   BSOD_COPY(bst,srcx,srcy,w,h,tox,toy); \
248   (bst)->queue[(bst)->pos-1].type = PIXMAP; \
249   } while (0)
250
251 /* Load a random image (or the desktop) onto the window.
252  */
253 #define BSOD_IMG(bst) do { \
254   ensure_queue (bst); \
255   (bst)->queue[(bst)->pos].type = IMG; \
256   (bst)->pos++; \
257   } while (0)
258
259 /* Jump around in the state table.  You can use this as the last thing 
260    in your state table to repeat the last N elements forever.
261  */
262 #define BSOD_LOOP(bst,off) do { \
263   ensure_queue (bst); \
264   (bst)->queue[(bst)->pos].type = LOOP; \
265   (bst)->queue[(bst)->pos].arg1 = (void *) (off); \
266   (bst)->pos++; \
267   } while (0)
268
269 /* Restart the whole thing from the beginning.
270  */
271 #define BSOD_RESET(bst) do { \
272   ensure_queue (bst); \
273   (bst)->queue[(bst)->pos].type = RESET; \
274   (bst)->pos++; \
275   } while (0)
276
277
278 static void
279 ensure_queue (struct bsod_state *bst)
280 {
281   int n;
282   if (bst->pos + 1 < bst->queue_size)
283     return;
284
285   n = bst->queue_size + 10;
286   if (n < 100) n *= 2;
287   n *= 1.2;
288
289   bst->queue = (struct bsod_event *) 
290     realloc (bst->queue, n * sizeof(*bst->queue));
291   if (!bst->queue) abort();
292   memset (bst->queue + bst->queue_size, 0, 
293           (n - bst->queue_size) * sizeof(*bst->queue));
294   bst->queue_size = n;
295 }
296
297
298 static void
299 position_for_text (struct bsod_state *bst, const char *line)
300 {
301   int max_width = 0;
302
303   const char *start = line;
304
305   if (bst->queue[bst->pos].type != LEFT &&
306       bst->queue[bst->pos].type != LEFT_FULL)
307     while (*start)
308       {
309         int dir, ascent, descent;
310         XCharStruct ov;
311         const char *end = start;
312         while (*end && *end != '\r' && *end != '\n')
313           end++;
314
315         XTextExtents (bst->font, start, end-start,
316                       &dir, &ascent, &descent, &ov);
317         if (ov.width > max_width)
318           max_width = ov.width;
319         if (!*end) break;
320         start = end+1;
321       }
322
323   switch (bst->queue[bst->pos].type) {
324   case LEFT:
325   case LEFT_FULL:
326     bst->current_left = bst->left_margin;
327     break;
328   case RIGHT:
329   case RIGHT_FULL:
330     bst->x = max_width - bst->right_margin;
331     bst->current_left = bst->x;
332     break;
333   case CENTER:
334   case CENTER_FULL:
335     {
336       int w = (bst->xgwa.width - bst->left_margin - bst->right_margin -
337                max_width);
338       if (w < 0) w = 0;
339       bst->x = bst->left_margin + (w / 2);
340       bst->current_left = bst->x;
341       break;
342     }
343   default:
344     abort();
345   }
346 }
347
348
349 static void
350 bst_crlf (struct bsod_state *bst)
351 {
352   int lh = bst->font->ascent + bst->font->descent;
353   bst->x = bst->current_left;
354   if (!bst->scroll_p ||
355       bst->y + lh < bst->xgwa.height - bst->bottom_margin)
356     bst->y += lh;
357   else
358     {
359       int w = bst->xgwa.width  - bst->right_margin - bst->left_margin;
360       int h = bst->xgwa.height - bst->top_margin - bst->bottom_margin;
361       XCopyArea (bst->dpy, bst->window, bst->window, bst->gc,
362                  bst->left_margin,
363                  bst->top_margin + lh,
364                  w, h - lh,
365                  bst->left_margin,
366                  bst->top_margin);
367       XClearArea (bst->dpy, bst->window,
368                   bst->left_margin, bst->top_margin + h - lh, w, lh, False);
369     }
370 }
371
372
373 static void
374 draw_char (struct bsod_state *bst, char c)
375 {
376   if (!c)
377     abort();
378   else if (c == '\r')
379     {
380       bst->x = bst->current_left;
381     }
382   else if (c == '\n')
383     {
384       if (bst->macx_eol_kludge)
385         {
386           /* Special case for the weird way OSX crashes print newlines... */
387           XDrawImageString (bst->dpy, bst->window, bst->gc, 
388                             bst->x, bst->y, " ", 1);
389           XDrawImageString (bst->dpy, bst->window, bst->gc, 
390                             bst->x, 
391                             bst->y + bst->font->ascent + bst->font->descent,
392                             " ", 1);
393         }
394       bst_crlf (bst);
395     }
396   else if (c == '\b')   /* backspace */
397     {
398       int cw = (bst->font->per_char
399                 ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
400                 : bst->font->min_bounds.width);
401       bst->x -= cw;
402       if (bst->x < bst->left_margin)
403         bst->x = bst->left_margin;
404     }
405   else
406     {
407       int dir, ascent, descent;
408       XCharStruct ov;
409       XTextExtents (bst->font, &c, 1, &dir, &ascent, &descent, &ov);
410
411       if (bst->wrap_p && 
412           bst->x + ov.width > bst->xgwa.width - bst->right_margin)
413         bst_crlf (bst);
414
415       XDrawImageString (bst->dpy, bst->window, bst->gc, 
416                         bst->x, bst->y, &c, 1);
417       bst->x += ov.width;
418     }
419 }
420
421
422 static long
423 bsod_pop (struct bsod_state *bst)
424 {
425   bsod_event_type type = bst->queue[bst->pos].type;
426
427   if (bst->draw_cb)
428     return bst->draw_cb (bst);
429
430   if (bst->pos < 0)   /* already done */
431     abort();
432
433   switch (type) {
434
435   case LEFT:   case LEFT_FULL:
436   case CENTER: case CENTER_FULL:
437   case RIGHT:  case RIGHT_FULL:
438     {
439       const char *s = (const char *) bst->queue[bst->pos].arg2;
440       char c;
441
442       if (! *s)
443         {
444           long delay = bst->line_delay;
445           bst->pos++;
446           bst->current_left = bst->left_margin;
447           return delay;
448         }
449
450       if (! bst->queue[bst->pos].arg3)    /* "done once" */
451         {
452           position_for_text (bst, s);
453           bst->queue[bst->pos].arg4 = (void *) bst->queue[bst->pos].type;
454           bst->queue[bst->pos].type = LEFT;
455
456           if (type == CENTER_FULL ||
457               type == LEFT_FULL ||
458               type == RIGHT_FULL)
459             {
460               XSetForeground (bst->dpy, bst->gc, bst->bg);
461               XFillRectangle (bst->dpy, bst->window, bst->gc,
462                               0,
463                               bst->y - bst->font->ascent,
464                               bst->xgwa.width,
465                               bst->font->ascent + bst->font->descent);
466               XSetForeground (bst->dpy, bst->gc, bst->fg);
467             }
468         }
469
470       c = *s++;
471       draw_char (bst, c);
472       bst->queue[bst->pos].arg2 = (void *) s;
473       bst->queue[bst->pos].arg3 = (void *) 1;  /* "done once" */
474
475       return (c == '\r' || c == '\n'
476               ? bst->line_delay
477               : bst->char_delay);
478     }
479   case INVERT:
480     {
481       unsigned long swap = bst->fg;
482       bst->fg = bst->bg;
483       bst->bg = swap;
484       XSetForeground (bst->dpy, bst->gc, bst->fg);
485       XSetBackground (bst->dpy, bst->gc, bst->bg);
486       bst->pos++;
487       return 0;
488     }
489   case COLOR:
490     {
491       bst->fg = (unsigned long) bst->queue[bst->pos].arg1;
492       bst->bg = (unsigned long) bst->queue[bst->pos].arg2;
493       XSetForeground (bst->dpy, bst->gc, bst->fg);
494       XSetBackground (bst->dpy, bst->gc, bst->bg);
495       bst->pos++;
496       return 0;
497     }
498   case MOVETO:
499     {
500       bst->x = (long) bst->queue[bst->pos].arg1;
501       bst->y = (long) bst->queue[bst->pos].arg2;
502       bst->pos++;
503       return 0;
504     }
505   case RECT:
506     {
507       int f = (long) bst->queue[bst->pos].arg1;
508       int x = (long) bst->queue[bst->pos].arg2;
509       int y = (long) bst->queue[bst->pos].arg3;
510       int w = (long) bst->queue[bst->pos].arg4;
511       int h = (long) bst->queue[bst->pos].arg5;
512       if (f)
513         XFillRectangle (bst->dpy, bst->window, bst->gc, x, y, w, h);
514       else
515         XDrawRectangle (bst->dpy, bst->window, bst->gc, x, y, w, h);
516       bst->pos++;
517       return 0;
518     }
519   case COPY:
520   case PIXMAP:
521     {
522       int srcx = (long) bst->queue[bst->pos].arg1;
523       int srcy = (long) bst->queue[bst->pos].arg2;
524       int w    = (long) bst->queue[bst->pos].arg3;
525       int h    = (long) bst->queue[bst->pos].arg4;
526       int tox  = (long) bst->queue[bst->pos].arg5;
527       int toy  = (long) bst->queue[bst->pos].arg6;
528       XCopyArea (bst->dpy, 
529                  (type == PIXMAP ? bst->pixmap : bst->window), 
530                  bst->window, bst->gc,
531                  srcx, srcy, w, h, tox, toy);
532       bst->pos++;
533       return 0;
534     }
535   case IMG:
536     {
537       if (bst->img_loader) abort();
538       bst->img_loader = load_image_async_simple (0, bst->xgwa.screen, 
539                                                  bst->window, bst->window,
540                                                  0, 0);
541       bst->pos++;
542       return 0;
543     }
544   case PAUSE:
545     {
546       long delay = (long) bst->queue[bst->pos].arg1;
547       bst->pos++;
548       return delay;
549     }
550   case CHAR_DELAY:
551     {
552       bst->char_delay = (long) bst->queue[bst->pos].arg1;
553       bst->pos++;
554       return 0;
555     }
556   case LINE_DELAY:
557     {
558       bst->line_delay = (long) bst->queue[bst->pos].arg1;
559       bst->pos++;
560       return 0;
561     }
562   case MARGINS:
563     {
564       bst->left_margin  = (long) bst->queue[bst->pos].arg1;
565       bst->right_margin = (long) bst->queue[bst->pos].arg2;
566       bst->pos++;
567       return 0;
568     }
569   case CURSOR_BLOCK:
570   case CURSOR_LINE:
571     {
572       long delay = (long) bst->queue[bst->pos].arg1;
573       long count = (long) bst->queue[bst->pos].arg2;
574       int ox = bst->x;
575
576       if (type == CURSOR_BLOCK)
577         {
578           unsigned long swap = bst->fg;
579           bst->fg = bst->bg;
580           bst->bg = swap;
581           XSetForeground (bst->dpy, bst->gc, bst->fg);
582           XSetBackground (bst->dpy, bst->gc, bst->bg);
583           draw_char (bst, ' ');
584         }
585       else
586         {
587           draw_char (bst, (count & 1 ? ' ' : '_'));
588           draw_char (bst, ' ');
589         }
590
591       bst->x = ox;
592
593       count--;
594       bst->queue[bst->pos].arg2 = (void *) count;
595       if (count <= 0)
596         bst->pos++;
597
598       return delay;
599     }
600   case LOOP:
601     {
602       long off = (long) bst->queue[bst->pos].arg1;
603       bst->pos += off;
604       if (bst->pos < 0 || bst->pos >= bst->queue_size)
605         abort();
606       return 0;
607     }
608   case RESET:
609     {
610       int i;
611       for (i = 0; i < bst->queue_size; i++)
612         switch (bst->queue[i].type) {
613         case LEFT:   case LEFT_FULL:
614         case CENTER: case CENTER_FULL:
615         case RIGHT:  case RIGHT_FULL:
616           bst->queue[i].arg2 = bst->queue[i].arg1;
617           bst->queue[i].arg3 = 0;
618           bst->queue[i].type = (bsod_event_type) bst->queue[i].arg4;
619           break;
620         default: break;
621         }
622       bst->pos = 0;
623       return 0;
624     }
625   case EOF:
626     {
627       bst->pos = -1;
628       return -1;
629     }
630   default:
631     break;
632   }
633   abort();
634 }
635
636
637 static struct bsod_state *
638 make_bsod_state (Display *dpy, Window window,
639                  const char *name, const char *class)
640 {
641   XGCValues gcv;
642   struct bsod_state *bst;
643   char buf1[1024], buf2[1024];
644   char buf3[1024], buf4[1024];
645   const char *font1, *font2;
646
647   bst = (struct bsod_state *) calloc (1, sizeof (*bst));
648   bst->queue_size = 10;
649   bst->queue = (struct bsod_event *) calloc (bst->queue_size,
650                                              sizeof (*bst->queue));
651   bst->dpy = dpy;
652   bst->window = window;
653   XGetWindowAttributes (dpy, window, &bst->xgwa);
654
655   /* If the window is small:
656        use ".font" if it is loadable, else use ".font2".
657
658      If the window is big:
659        use ".bigFont" if it is loadable, else use ".bigFont2".
660    */
661   if (
662 # ifdef USE_IPHONE
663       1
664 # else
665       bst->xgwa.height < 640
666 # endif
667       )
668     {
669       sprintf (buf1, "%.100s.font", name);
670       sprintf (buf2, "%.100s.font", class);
671       sprintf (buf3, "%.100s.font2", name);
672       sprintf (buf4, "%.100s.font2", class);
673     }
674   else
675     {
676       sprintf (buf1, "%.100s.bigFont", name);
677       sprintf (buf2, "%.100s.bigFont", class);
678       sprintf (buf3, "%.100s.bigFont2", name);
679       sprintf (buf4, "%.100s.bigFont2", class);
680     }
681
682   font1 = get_string_resource (dpy, buf1, buf2);
683   font2 = get_string_resource (dpy, buf3, buf4);
684
685   if (font1)
686     bst->font = XLoadQueryFont (dpy, font1);
687   if (! bst->font && font2)
688     bst->font = XLoadQueryFont (dpy, font2);
689
690   /* If neither of those worked, try some defaults. */
691
692   if (! bst->font)
693     bst->font = XLoadQueryFont (dpy,"-*-courier-bold-r-*-*-*-120-*-*-m-*-*-*");
694   if (! bst->font)
695     bst->font = XLoadQueryFont (dpy, "fixed");
696   if (! bst->font)
697     abort();
698
699   gcv.font = bst->font->fid;
700
701   sprintf (buf1, "%.100s.foreground", name);
702   sprintf (buf2, "%.100s.Foreground", class);
703   bst->fg = gcv.foreground = get_pixel_resource (dpy, bst->xgwa.colormap,
704                                                  buf1, buf2);
705   sprintf (buf1, "%.100s.background", name);
706   sprintf (buf2, "%.100s.Background", class);
707   bst->bg = gcv.background = get_pixel_resource (dpy, bst->xgwa.colormap,
708                                                  buf1, buf2);
709   bst->gc = XCreateGC (dpy, window, GCFont|GCForeground|GCBackground, &gcv);
710
711 #ifdef HAVE_COCOA
712   jwxyz_XSetAntiAliasing (dpy, bst->gc, False);
713 #endif
714
715   bst->left_margin = bst->right_margin = 10;
716   bst->x = bst->left_margin;
717   bst->y = bst->font->ascent + bst->left_margin;
718
719   XSetWindowBackground (dpy, window, gcv.background);
720   return bst;
721 }
722
723
724 static void
725 free_bsod_state (struct bsod_state *bst)
726 {
727   int i;
728
729   if (bst->free_cb)
730     bst->free_cb (bst);
731   if (bst->pixmap)
732     XFreePixmap(bst->dpy, bst->pixmap);
733
734   XFreeFont (bst->dpy, bst->font);
735   XFreeGC (bst->dpy, bst->gc);
736
737   for (i = 0; i < bst->queue_size; i++)
738     switch (bst->queue[i].type) {
739     case LEFT:   case LEFT_FULL:
740     case RIGHT:  case RIGHT_FULL:
741     case CENTER: case CENTER_FULL:
742       free ((char *) bst->queue[i].arg1);
743       break;
744     default:
745       break;
746     }
747
748   free (bst->queue);
749   free (bst);
750 }
751
752
753 static Pixmap
754 double_pixmap (Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
755                int pix_w, int pix_h)
756 {
757   int x, y;
758   Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
759   XImage *i1 = XGetImage(dpy, pixmap, 0, 0, pix_w, pix_h, ~0L, ZPixmap);
760   XImage *i2 = XCreateImage(dpy, visual, depth, ZPixmap, 0, 0,
761                             pix_w*2, pix_h*2, 8, 0);
762   i2->data = (char *) calloc(i2->height, i2->bytes_per_line);
763   for (y = 0; y < pix_h; y++)
764     for (x = 0; x < pix_w; x++)
765       {
766         unsigned long p = XGetPixel(i1, x, y);
767         XPutPixel(i2, x*2,   y*2,   p);
768         XPutPixel(i2, x*2+1, y*2,   p);
769         XPutPixel(i2, x*2,   y*2+1, p);
770         XPutPixel(i2, x*2+1, y*2+1, p);
771       }
772   free(i1->data); i1->data = 0;
773   XDestroyImage(i1);
774   XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
775   free(i2->data); i2->data = 0;
776   XDestroyImage(i2);
777   XFreePixmap(dpy, pixmap);
778   return p2;
779 }
780
781
782 /*****************************************************************************
783  *****************************************************************************/
784
785 static struct bsod_state *
786 windows_31 (Display *dpy, Window window)
787 {
788   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
789   BSOD_INVERT (bst);
790   BSOD_TEXT   (bst, CENTER, "Windows\n");
791   BSOD_INVERT (bst);
792   BSOD_TEXT   (bst, CENTER,
793                "A fatal exception 0E has occured at F0AD:42494C4C\n"
794                "the current application will be terminated.\n"
795                "\n"
796                "* Press any key to terminate the current application.\n"
797                "* Press CTRL+ALT+DELETE again to restart your computer.\n"
798                "  You will lose any unsaved information in all applications.\n"
799                "\n"
800                "\n");
801   BSOD_TEXT   (bst, CENTER, "Press any key to continue");
802
803   bst->y = ((bst->xgwa.height -
804              ((bst->font->ascent + bst->font->descent) * 9))
805             / 2);
806
807   XClearWindow (dpy, window);
808   return bst;
809 }
810
811
812 static struct bsod_state *
813 windows_nt (Display *dpy, Window window)
814 {
815   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
816
817   BSOD_TEXT (bst, LEFT,
818    "*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
819    "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
820    "\n"
821    "Dll Base Date Stamp - Name             Dll Base Date Stamp - Name\n"
822    "80100000 2be154c9 - ntoskrnl.exe       80400000 2bc153b0 - hal.dll\n"
823    "80258000 2bd49628 - ncrc710.sys        8025c000 2bd49688 - SCSIPORT.SYS \n"
824    "80267000 2bd49683 - scsidisk.sys       802a6000 2bd496b9 - Fastfat.sys\n"
825    "fa800000 2bd49666 - Floppy.SYS         fa810000 2bd496db - Hpfs_Rec.SYS\n"
826    "fa820000 2bd49676 - Null.SYS           fa830000 2bd4965a - Beep.SYS\n"
827    "fa840000 2bdaab00 - i8042prt.SYS       fa850000 2bd5a020 - SERMOUSE.SYS\n"
828    "fa860000 2bd4966f - kbdclass.SYS       fa870000 2bd49671 - MOUCLASS.SYS\n"
829    "fa880000 2bd9c0be - Videoprt.SYS       fa890000 2bd49638 - NCC1701E.SYS\n"
830    "fa8a0000 2bd4a4ce - Vga.SYS            fa8b0000 2bd496d0 - Msfs.SYS\n"
831    "fa8c0000 2bd496c3 - Npfs.SYS           fa8e0000 2bd496c9 - Ntfs.SYS\n"
832    "fa940000 2bd496df - NDIS.SYS           fa930000 2bd49707 - wdlan.sys\n"
833    "fa970000 2bd49712 - TDI.SYS            fa950000 2bd5a7fb - nbf.sys\n"
834    "fa980000 2bd72406 - streams.sys        fa9b0000 2bd4975f - ubnb.sys\n"
835    "fa9c0000 2bd5bfd7 - usbser.sys         fa9d0000 2bd4971d - netbios.sys\n"
836    "fa9e0000 2bd49678 - Parallel.sys       fa9f0000 2bd4969f - serial.SYS\n"
837    "faa00000 2bd49739 - mup.sys            faa40000 2bd4971f - SMBTRSUP.SYS\n"
838    "faa10000 2bd6f2a2 - srv.sys            faa50000 2bd4971a - afd.sys\n"
839    "faa60000 2bd6fd80 - rdr.sys            faaa0000 2bd49735 - bowser.sys\n"
840    "\n"
841    "Address dword dump Dll Base                                      - Name\n"
842    "801afc20 80106fc0 80106fc0 00000000 00000000 80149905 : "
843      "fa840000 - i8042prt.SYS\n"
844    "801afc24 80149905 80149905 ff8e6b8c 80129c2c ff8e6b94 : "
845      "8025c000 - SCSIPORT.SYS\n"
846    "801afc2c 80129c2c 80129c2c ff8e6b94 00000000 ff8e6b94 : "
847      "80100000 - ntoskrnl.exe\n"
848    "801afc34 801240f2 80124f02 ff8e6df4 ff8e6f60 ff8e6c58 : "
849      "80100000 - ntoskrnl.exe\n"
850    "801afc54 80124f16 80124f16 ff8e6f60 ff8e6c3c 8015ac7e : "
851      "80100000 - ntoskrnl.exe\n"
852    "801afc64 8015ac7e 8015ac7e ff8e6df4 ff8e6f60 ff8e6c58 : "
853      "80100000 - ntoskrnl.exe\n"
854    "801afc70 80129bda 80129bda 00000000 80088000 80106fc0 : "
855      "80100000 - ntoskrnl.exe\n"
856    "\n"
857    "Kernel Debugger Using: COM2 (Port 0x2f8, Baud Rate 19200)\n"
858    "Restart and set the recovery options in the system control panel\n"
859    "or the /CRASHDEBUG system start option. If this message reappears,\n"
860    "contact your system administrator or technical support group."
861    );
862
863   bst->line_delay = 750;
864
865   XClearWindow (dpy, window);
866   return bst;
867 }
868
869
870 static struct bsod_state *
871 windows_2k (Display *dpy, Window window)
872 {
873   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
874
875   BSOD_TEXT (bst, LEFT,
876     "*** STOP: 0x000000D1 (0xE1D38000,0x0000001C,0x00000000,0xF09D42DA)\n"
877     "DRIVER_IRQL_NOT_LESS_OR_EQUAL \n"
878     "\n"
879     "*** Address F09D42DA base at F09D4000, DateStamp 39f459ff - CRASHDD.SYS\n"
880     "\n"
881     "Beginning dump of physical memory\n");
882   BSOD_PAUSE (bst, 4000000);
883   BSOD_TEXT (bst, LEFT,
884     "Physical memory dump complete. Contact your system administrator or\n"
885     "technical support group.\n");
886
887   bst->left_margin = 40;
888   bst->y = (bst->font->ascent + bst->font->descent) * 10;
889   bst->line_delay = 750;
890
891   XClearWindow (dpy, window);
892   return bst;
893 }
894
895
896 static struct bsod_state *
897 windows_me (Display *dpy, Window window)
898 {
899   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
900
901   BSOD_TEXT (bst, LEFT,
902     "Windows protection error.  You need to restart your computer.\n\n"
903     "System halted.");
904   BSOD_CURSOR (bst, CURSOR_LINE, 120000, 999999);
905
906   bst->left_margin = 40;
907   bst->y = ((bst->xgwa.height -
908              ((bst->font->ascent + bst->font->descent) * 3))
909             / 2);
910
911   XClearWindow (dpy, window);
912   return bst;
913 }
914
915
916 static struct bsod_state *
917 windows_xp (Display *dpy, Window window)
918 {
919   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
920
921   BSOD_TEXT (bst, LEFT,  /* From Wm. Rhodes <xscreensaver@27.org> */
922       "A problem has been detected and windows has been shut down to prevent "
923       "damage\n"
924       "to your computer.\n"
925       "\n"
926       "If this is the first time you've seen this Stop error screen,\n"
927       "restart your computer. If this screen appears again, follow\n"
928       "these steps:\n"
929       "\n"
930       "Check to be sure you have adequate disk space. If a driver is\n"
931       "identified in the Stop message, disable the driver or check\n"
932       "with the manufacturer for driver updates. Try changing video\n"
933       "adapters.\n"
934       "\n"
935       "Check with your hardware vendor for any BIOS updates. Disable\n"
936       "BIOS memory options such as caching or shadowing. If you need\n"
937       "to use Safe Mode to remove or disable components, restart your\n"
938       "computer, press F8 to select Advanced Startup Options, and then\n"
939       "select Safe Mode.\n"
940       "\n"
941       "Technical information:\n"
942       "\n"
943       "*** STOP: 0x0000007E (0xC0000005,0xF88FF190,0x0xF8975BA0,0xF89758A0)\n"
944       "\n"
945       "\n"
946       "***  EPUSBDSK.sys - Address F88FF190 base at FF88FE000, datestamp "
947       "3b9f3248\n"
948       "\n"
949       "Beginning dump of physical memory\n");
950   BSOD_PAUSE (bst, 4000000);
951   BSOD_TEXT (bst, LEFT,
952       "Physical memory dump complete.\n"
953       "Contact your system administrator or technical support group for "
954       "further\n"
955       "assistance.\n");
956
957   XClearWindow (dpy, window);
958   return bst;
959 }
960
961
962 static struct bsod_state *
963 windows_lh (Display *dpy, Window window)
964 {
965   struct bsod_state *bst = 
966     make_bsod_state (dpy, window, "windowslh", "WindowsLH");
967
968   unsigned long fg = bst->fg;
969   unsigned long bg = bst->bg;
970   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
971                                           "windowslh.background2",
972                                           "WindowsLH.Background");
973
974   /* The "RSOD" that appeared with "Windows Longhorn 5048.050401-0536_x86fre"
975      As reported by http://joi.ito.com/RedScreen.jpg
976    */
977   BSOD_COLOR (bst, bg, bg2);
978   BSOD_TEXT (bst, CENTER_FULL, "Windows Boot Error\n");
979   BSOD_COLOR (bst, fg, bg);
980   BSOD_TEXT (bst, CENTER,
981      "\n"
982      "Windows Boot Manager has experienced a problem.\n"
983      "\n"
984      "\n"
985      "    Status: 0xc000000f\n"
986      "\n"
987      "\n"
988      "\n"
989      "    Info: An error occurred transferring exectuion."  /* (sic) */
990      "\n"
991      "\n"
992      "\n"
993      "You can try to recover the system with the Microsoft Windows "
994      "System Recovery\n"
995      "Tools. (You might need to restart the system manually.)\n"
996      "\n"
997      "If the problem continues, please contact your system administrator "
998      "or computer\n"
999      "manufacturer.\n"
1000      );
1001   BSOD_MOVETO (bst, bst->left_margin, bst->xgwa.height - bst->font->descent);
1002   BSOD_COLOR (bst, bg, bg2);
1003   BSOD_TEXT (bst, LEFT_FULL, " SPACE=Continue\n");
1004
1005   bst->y = bst->font->ascent;
1006
1007   XClearWindow (dpy, window);
1008   return bst;
1009 }
1010
1011
1012 static struct bsod_state *
1013 windows_other (Display *dpy, Window window)
1014 {
1015   /* Lump all of the 2K-ish crashes together and select them randomly...
1016    */
1017   int which = (random() % 4);
1018   switch (which) {
1019   case 0: return windows_2k (dpy, window); break;
1020   case 1: return windows_me (dpy, window); break;
1021   case 2: return windows_xp (dpy, window); break;
1022   case 3: return windows_lh (dpy, window); break;
1023   default: abort(); break;
1024   }
1025 }
1026
1027
1028 /* As seen in Portal 2.  By jwz.
1029  */
1030 static struct bsod_state *
1031 glados (Display *dpy, Window window)
1032 {
1033   struct bsod_state *bst = make_bsod_state (dpy, window, "glaDOS", "GlaDOS");
1034   const char * panicstr[] = {
1035     "\n",
1036     "MOLTEN CORE WARNING\n",
1037     "\n",
1038     "An operator error exception has occurred at FISSREAC0020093:09\n",
1039     "FISSREAC0020077:14 FISSREAC0020023:17 FISSREAC0020088:22\n",
1040     "neutron multiplication rate at spikevalue 99999999\n",
1041     "\n",
1042     "* Press any key to vent radiological emissions into atmosphere.\n",
1043     "* Consult reactor core manual for instructions on proper reactor core\n",
1044     "maintenance and repair.\n",
1045     "\n",
1046     "Press any key to continue\n",
1047   };
1048
1049   int i;
1050
1051   bst->y = ((bst->xgwa.height -
1052              ((bst->font->ascent + bst->font->descent) * countof(panicstr)))
1053             / 2);
1054
1055   BSOD_MOVETO (bst, 0, bst->y);
1056   BSOD_INVERT (bst);
1057   BSOD_TEXT   (bst,  CENTER, "OPERATOR ERROR\n");
1058   BSOD_INVERT (bst);
1059   for (i = 0; i < countof(panicstr); i++)
1060     BSOD_TEXT (bst, CENTER, panicstr[i]);
1061   BSOD_PAUSE (bst, 1000000);
1062   BSOD_INVERT (bst);
1063   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
1064   BSOD_INVERT (bst);
1065   BSOD_PAUSE (bst, 250000);
1066   BSOD_RESET (bst);
1067
1068   XClearWindow (dpy, window);
1069   return bst;
1070 }
1071
1072
1073
1074 /* SCO OpenServer 5 panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
1075  */
1076 static struct bsod_state *
1077 sco (Display *dpy, Window window)
1078 {
1079   struct bsod_state *bst = make_bsod_state (dpy, window, "sco", "SCO");
1080
1081   BSOD_TEXT (bst, LEFT,
1082      "Unexpected trap in kernel mode:\n"
1083      "\n"
1084      "cr0 0x80010013     cr2  0x00000014     cr3 0x00000000  tlb  0x00000000\n"
1085      "ss  0x00071054    uesp  0x00012055     efl 0x00080888  ipl  0x00000005\n"
1086      "cs  0x00092585     eip  0x00544a4b     err 0x004d4a47  trap 0x0000000E\n"
1087      "eax 0x0045474b     ecx  0x0042544b     edx 0x57687920  ebx  0x61726520\n"
1088      "esp 0x796f7520     ebp  0x72656164     esi 0x696e6720  edi  0x74686973\n"
1089      "ds  0x3f000000     es   0x43494c48     fs  0x43525343  gs   0x4f4d4b53\n"
1090      "\n"
1091      "PANIC: k_trap - kernel mode trap type 0x0000000E\n"
1092      "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n"
1093     );
1094   BSOD_CHAR_DELAY (bst, 100000);
1095   BSOD_TEXT (bst, LEFT,
1096     "................................................................."
1097     "..............\n"
1098     );
1099   BSOD_CHAR_DELAY (bst, 0);
1100   BSOD_TEXT (bst, LEFT,
1101      "5023 pages dumped\n"
1102      "\n"
1103      "\n"
1104      );
1105   BSOD_PAUSE (bst, 2000000);
1106   BSOD_TEXT (bst, LEFT,
1107      "**   Safe to Power Off   **\n"
1108      "           - or -\n"
1109      "** Press Any Key to Reboot **\n"
1110     );
1111
1112   bst->y = ((bst->xgwa.height -
1113              ((bst->font->ascent + bst->font->descent) * 18)));
1114
1115   XClearWindow (dpy, window);
1116   return bst;
1117 }
1118
1119
1120 /* Linux (sparc) panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
1121  */
1122 static struct bsod_state *
1123 sparc_linux (Display *dpy, Window window)
1124 {
1125   struct bsod_state *bst = make_bsod_state (dpy, window, "sco", "SCO");
1126   bst->scroll_p = True;
1127   bst->y = bst->xgwa.height - bst->font->ascent - bst->font->descent;
1128
1129   BSOD_TEXT (bst, LEFT,
1130         "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
1131         "Unable to handle kernel paging request at virtual address f0d4a000\n"
1132         "tsk->mm->context = 00000014\n"
1133         "tsk->mm->pgd = f26b0000\n"
1134         "              \\|/ ____ \\|/\n"
1135         "              \"@'/ ,. \\`@\"\n"
1136         "              /_| \\__/ |_\\\n"
1137         "                 \\__U_/\n"
1138         "gawk(22827): Oops\n"
1139         "PSR: 044010c1 PC: f001c2cc NPC: f001c2d0 Y: 00000000\n"
1140         "g0: 00001000 g1: fffffff7 g2: 04401086 g3: 0001eaa0\n"
1141         "g4: 000207dc g5: f0130400 g6: f0d4a018 g7: 00000001\n"
1142         "o0: 00000000 o1: f0d4a298 o2: 00000040 o3: f1380718\n"
1143         "o4: f1380718 o5: 00000200 sp: f1b13f08 ret_pc: f001c2a0\n"
1144         "l0: efffd880 l1: 00000001 l2: f0d4a230 l3: 00000014\n"
1145         "l4: 0000ffff l5: f0131550 l6: f012c000 l7: f0130400\n"
1146         "i0: f1b13fb0 i1: 00000001 i2: 00000002 i3: 0007c000\n"
1147         "i4: f01457c0 i5: 00000004 i6: f1b13f70 i7: f0015360\n"
1148         "Instruction DUMP:\n"
1149     );
1150
1151   XClearWindow (dpy, window);
1152   return bst;
1153 }
1154
1155
1156 /* BSD Panic by greywolf@starwolf.com - modeled after the Linux panic above.
1157    By Grey Wolf <greywolf@siteROCK.com>
1158  */
1159 static struct bsod_state *
1160 bsd (Display *dpy, Window window)
1161 {
1162   struct bsod_state *bst = make_bsod_state (dpy, window, "bsd", "BSD");
1163
1164   const char * const panicstr[] = {
1165     "panic: ifree: freeing free inode\n",
1166     "panic: blkfree: freeing free block\n",
1167     "panic: improbability coefficient below zero\n",
1168     "panic: cgsixmmap\n",
1169     "panic: crazy interrupts\n",
1170     "panic: nmi\n",
1171     "panic: attempted windows install\n",
1172     "panic: don't\n",
1173     "panic: free inode isn't\n",
1174     "panic: cpu_fork: curproc\n",
1175     "panic: malloc: out of space in kmem_map\n",
1176     "panic: vogon starship detected\n",
1177     "panic: teleport chamber: out of order\n",
1178     "panic: Brain fried - core dumped\n"
1179    };
1180   int i, n, b;
1181   char syncing[80], bbuf[5];
1182
1183   for (i = 0; i < sizeof(syncing); i++)
1184     syncing[i] = 0;
1185
1186   i = (random() % (sizeof(panicstr) / sizeof(*panicstr)));
1187   BSOD_TEXT (bst, LEFT, panicstr[i]);
1188   BSOD_TEXT (bst, LEFT, "Syncing disks: ");
1189
1190   b = (random() % 40);
1191   for (n = 0; (n < 20) && (b > 0); n++)
1192     {
1193       if (i)
1194         {
1195           i = (random() & 0x7);
1196           b -= (random() & 0xff) % 20;
1197           if (b < 0)
1198             b = 0;
1199         }
1200       sprintf (bbuf, "%d ", b);
1201       BSOD_TEXT (bst, LEFT, bbuf);
1202       BSOD_PAUSE (bst, 1000000);
1203     }
1204
1205   BSOD_TEXT (bst, LEFT, "\n");
1206   BSOD_TEXT (bst, LEFT, (b ? "damn!" : "sunk!"));
1207   BSOD_TEXT (bst, LEFT, "\nRebooting\n");
1208
1209   bst->y = ((bst->xgwa.height -
1210              ((bst->font->ascent + bst->font->descent) * 4)));
1211
1212   XClearWindow (dpy, window);
1213   return bst;
1214 }
1215
1216
1217 static struct bsod_state *
1218 amiga (Display *dpy, Window window)
1219 {
1220   struct bsod_state *bst = make_bsod_state (dpy, window, "amiga", "Amiga");
1221
1222   Pixmap pixmap = 0;
1223   int pix_w = 0, pix_h = 0;
1224   int height;
1225   int lw = 10;
1226
1227   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
1228                                           "amiga.background2",
1229                                           "Amiga.Background");
1230
1231 # ifdef DO_XPM
1232   pixmap = xpm_data_to_pixmap (dpy, window, (char **) amiga_hand,
1233                                &pix_w, &pix_h, 0);
1234 # endif /* DO_XPM */
1235
1236   if (pixmap && bst->xgwa.height > 600) /* scale up the bitmap */
1237     {
1238       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
1239                               pixmap, pix_w, pix_h);
1240       pix_w *= 2;
1241       pix_h *= 2;
1242     }
1243
1244   XSetLineAttributes (dpy, bst->gc, lw, LineSolid, CapButt, JoinMiter);
1245
1246   height = (bst->font->ascent + bst->font->descent) * 6;
1247
1248   BSOD_PAUSE (bst, 2000000);
1249   BSOD_COPY (bst, 0, 0, bst->xgwa.width, bst->xgwa.height - height, 0, height);
1250
1251   BSOD_INVERT (bst);
1252   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, height);
1253   BSOD_INVERT (bst);
1254   BSOD_TEXT (bst, CENTER,
1255              "\n"
1256              "Software failure.  Press left mouse button to continue.\n"
1257              "Guru Meditation #00000003.00C01570"
1258              );
1259   BSOD_RECT (bst, False, lw/2, lw/2, bst->xgwa.width - lw, height);
1260   BSOD_PAUSE (bst, 1000000);
1261   BSOD_INVERT (bst);
1262   BSOD_LOOP (bst, -3);
1263
1264   XSetWindowBackground (dpy, window, bg2);
1265   XClearWindow (dpy, window);
1266   XSetWindowBackground (dpy, window, bst->bg);
1267
1268   if (pixmap)
1269     {
1270       int x = (bst->xgwa.width - pix_w) / 2;
1271       int y = ((bst->xgwa.height - pix_h) / 2);
1272       XCopyArea (dpy, pixmap, bst->window, bst->gc, 0, 0, pix_w, pix_h, x, y);
1273     }
1274
1275   bst->y += lw;
1276
1277   return bst;
1278 }
1279
1280
1281
1282 /* Atari ST, by Marcus Herbert <rhoenie@nobiscum.de>
1283    Marcus had this to say:
1284
1285         Though I still have my Atari somewhere, I hardly remember
1286         the meaning of the bombs. I think 9 bombs was "bus error" or
1287         something like that.  And you often had a few bombs displayed
1288         quickly and then the next few ones coming up step by step.
1289         Perhaps somebody else can tell you more about it..  its just
1290         a quick hack :-}
1291  */
1292 static struct bsod_state *
1293 atari (Display *dpy, Window window)
1294 {
1295   struct bsod_state *bst = make_bsod_state (dpy, window, "atari", "Atari");
1296
1297   Pixmap pixmap = 0;
1298   int pix_w = atari_width;
1299   int pix_h = atari_height;
1300   int offset;
1301   int i, x, y;
1302
1303   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) atari_bits,
1304                                         pix_w, pix_h,
1305                                         bst->fg, bst->bg, bst->xgwa.depth);
1306   pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
1307                           pixmap, pix_w, pix_h);
1308   pix_w *= 2;
1309   pix_h *= 2;
1310
1311   offset = pix_w;
1312   x = 0;
1313   y = bst->xgwa.height/2;
1314   if (y < 0) y = 0;
1315
1316   for (i = 1; i< 7; i++)
1317     BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y);
1318
1319   for (; i< 10; i++) 
1320     {
1321       BSOD_PAUSE (bst, 1000000);
1322       BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y);
1323     }
1324
1325   XClearWindow (dpy, window);
1326   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
1327   XFreePixmap (dpy, pixmap);
1328
1329   return bst;
1330 }
1331
1332
1333 static struct bsod_state *
1334 mac (Display *dpy, Window window)
1335 {
1336   struct bsod_state *bst = make_bsod_state (dpy, window, "mac", "Mac");
1337
1338   Pixmap pixmap = 0;
1339   int pix_w = mac_width;
1340   int pix_h = mac_height;
1341   int offset = mac_height * 4;
1342   int i;
1343
1344   const char *string = ("0 0 0 0 0 0 0 F\n"
1345                         "0 0 0 0 0 0 0 3");
1346
1347   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits,
1348                                        mac_width, mac_height,
1349                                        bst->fg, bst->bg, bst->xgwa.depth);
1350
1351   for (i = 0; i < 2; i++)
1352     {
1353       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
1354                               pixmap, pix_w, pix_h);
1355       pix_w *= 2; pix_h *= 2;
1356     }
1357
1358   bst->x = (bst->xgwa.width - pix_w) / 2;
1359   bst->y = (((bst->xgwa.height + offset) / 2) -
1360             pix_h -
1361             (bst->font->ascent + bst->font->descent) * 2);
1362   if (bst->y < 0) bst->y = 0;
1363
1364   XClearWindow (dpy, window);
1365   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, bst->x, bst->y);
1366   XFreePixmap (dpy, pixmap);
1367
1368   bst->y += offset + bst->font->ascent + bst->font->descent;
1369   BSOD_TEXT (bst, CENTER, string);
1370
1371   return bst;
1372 }
1373
1374
1375 static struct bsod_state *
1376 macsbug (Display *dpy, Window window)
1377 {
1378   struct bsod_state *bst = make_bsod_state (dpy, window, "macsbug", "MacsBug");
1379
1380   __extension__
1381   const char *left = ("    SP     \n"
1382                       " 04EB0A58  \n"
1383                       "58 00010000\n"
1384                       "5C 00010000\n"
1385                       "   ........\n"
1386                       "60 00000000\n"
1387                       "64 000004EB\n"
1388                       "   ........\n"
1389                       "68 0000027F\n"
1390                       "6C 2D980035\n"
1391                       "   ....-..5\n"
1392                       "70 00000054\n"
1393                       "74 0173003E\n"
1394                       "   ...T.s.>\n"
1395                       "78 04EBDA76\n"
1396                       "7C 04EBDA8E\n"
1397                       "   .S.L.a.U\n"
1398                       "80 00000000\n"
1399                       "84 000004EB\n"
1400                       "   ........\n"
1401                       "88 00010000\n"
1402                       "8C 00010000\n"
1403                       "   ...{3..S\n"
1404                       "\n"
1405                       "\n"
1406                       " CurApName \n"
1407                       "  Finder   \n"
1408                       "\n"
1409                       " 32-bit VM \n"
1410                       "SR Smxnzvc0\n"
1411                       "D0 04EC0062\n"
1412                       "D1 00000053\n"
1413                       "D2 FFFF0100\n"
1414                       "D3 00010000\n"
1415                       "D4 00010000\n"
1416                       "D5 04EBDA76\n"
1417                       "D6 04EBDA8E\n"
1418                       "D7 00000001\n"
1419                       "\n"
1420                       "A0 04EBDA76\n"
1421                       "A1 04EBDA8E\n"
1422                       "A2 A0A00060\n"
1423                       "A3 027F2D98\n"
1424                       "A4 027F2E58\n"
1425                       "A5 04EC04F0\n"
1426                       "A6 04EB0A86\n"
1427                       "A7 04EB0A58");
1428   const char *bottom = ("  _A09D\n"
1429                         "     +00884    40843714     #$0700,SR         "
1430                         "                  ; A973        | A973\n"
1431                         "     +00886    40843765     *+$0400           "
1432                         "                                | 4A1F\n"
1433                         "     +00888    40843718     $0004(A7),([0,A7[)"
1434                         "                  ; 04E8D0AE    | 66B8");
1435   __extension__
1436   const char * body = ("PowerPC unmapped memory exception at 003AFDAC "
1437                                                 "BowelsOfTheMemoryMgr+04F9C\n"
1438                       " Calling chain using A6/R1 links\n"
1439                       "  Back chain  ISA  Caller\n"
1440                       "  00000000    PPC  28C5353C  __start+00054\n"
1441                       "  24DB03C0    PPC  28B9258C  main+0039C\n"
1442                       "  24DB0350    PPC  28B9210C  MainEvent+00494\n"
1443                       "  24DB02B0    PPC  28B91B40  HandleEvent+00278\n"
1444                       "  24DB0250    PPC  28B83DAC  DoAppleEvent+00020\n"
1445                       "  24DB0210    PPC  FFD3E5D0  "
1446                                                 "AEProcessAppleEvent+00020\n"
1447                       "  24DB0132    68K  00589468\n"
1448                       "  24DAFF8C    68K  00589582\n"
1449                       "  24DAFF26    68K  00588F70\n"
1450                       "  24DAFEB3    PPC  00307098  "
1451                                                 "EmToNatEndMoveParams+00014\n"
1452                       "  24DAFE40    PPC  28B9D0B0  DoScript+001C4\n"
1453                       "  24DAFDD0    PPC  28B9C35C  RunScript+00390\n"
1454                       "  24DAFC60    PPC  28BA36D4  run_perl+000E0\n"
1455                       "  24DAFC10    PPC  28BC2904  perl_run+002CC\n"
1456                       "  24DAFA80    PPC  28C18490  Perl_runops+00068\n"
1457                       "  24DAFA30    PPC  28BE6CC0  Perl_pp_backtick+000FC\n"
1458                       "  24DAF9D0    PPC  28BA48B8  Perl_my_popen+00158\n"
1459                       "  24DAF980    PPC  28C5395C  sfclose+00378\n"
1460                       "  24DAF930    PPC  28BA568C  free+0000C\n"
1461                       "  24DAF8F0    PPC  28BA6254  pool_free+001D0\n"
1462                       "  24DAF8A0    PPC  FFD48F14  DisposePtr+00028\n"
1463                       "  24DAF7C9    PPC  00307098  "
1464                                                 "EmToNatEndMoveParams+00014\n"
1465                       "  24DAF780    PPC  003AA180  __DisposePtr+00010");
1466
1467   const char *s;
1468   int body_lines = 1;
1469
1470   int char_width, line_height;
1471   int col_right, row_top, row_bottom, page_right, page_bottom, body_top;
1472   int xoff, yoff;
1473
1474   unsigned long fg = bst->fg;
1475   unsigned long bg = bst->bg;
1476   unsigned long bc = get_pixel_resource (dpy, bst->xgwa.colormap,
1477                                          "macsbug.borderColor",
1478                                          "MacsBug.BorderColor");
1479
1480   for (s = body; *s; s++) if (*s == '\n') body_lines++;
1481
1482   char_width = (bst->font->per_char
1483                 ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
1484                 : bst->font->min_bounds.width);
1485   line_height = bst->font->ascent + bst->font->descent;
1486
1487   col_right   = char_width  * 12;  /* number of columns in `left' */
1488   page_bottom = line_height * 47;  /* number of lines in `left'   */
1489
1490   if (page_bottom > bst->xgwa.height) 
1491     page_bottom = bst->xgwa.height;
1492
1493   row_bottom = page_bottom - line_height;
1494   row_top    = row_bottom - (line_height * 4);
1495   page_right = col_right + (char_width * 88);
1496   body_top   = row_top - (line_height * body_lines);
1497
1498   page_bottom += 2;
1499   row_bottom += 2;
1500   body_top -= 4;
1501
1502   if (body_top > 4)
1503     body_top = 4;
1504
1505   xoff = (bst->xgwa.width  - page_right)  / 2;
1506   yoff = (bst->xgwa.height - page_bottom) / 2;
1507
1508   if (xoff < 0) xoff = 0;
1509   if (yoff < 0) yoff = 0;
1510
1511   BSOD_MARGINS (bst, xoff, yoff);
1512
1513   BSOD_COLOR (bst, bc, bg);
1514   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
1515   BSOD_COLOR (bst, bg, bg);
1516   BSOD_RECT (bst, True, xoff-2, yoff, page_right+4, page_bottom);
1517   BSOD_COLOR (bst, fg, bg);
1518
1519   BSOD_MOVETO (bst, xoff, yoff + line_height);
1520   BSOD_TEXT (bst, LEFT, left);
1521   BSOD_MOVETO (bst, xoff+col_right, yoff + row_top + line_height);
1522   BSOD_TEXT (bst, LEFT, bottom);
1523
1524   BSOD_RECT (bst, True, xoff + col_right, yoff, 2, page_bottom);
1525   BSOD_RECT (bst, True, xoff + col_right, yoff + row_top, 
1526              page_right - col_right, 1);
1527   BSOD_RECT (bst, True, xoff + col_right, yoff + row_bottom, 
1528              page_right - col_right, 1);
1529   BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom);
1530
1531   BSOD_LINE_DELAY (bst, 500);
1532   BSOD_MOVETO (bst, 
1533                xoff + col_right + char_width, 
1534                yoff + body_top + line_height);
1535   BSOD_MARGINS (bst, xoff + col_right + char_width, yoff);
1536   BSOD_TEXT (bst, LEFT, body);
1537
1538   BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom); /* again */
1539
1540   BSOD_RECT (bst, False,
1541              xoff + col_right + (char_width/2)+2,
1542              yoff + row_bottom + 2,
1543              0,
1544              page_bottom - row_bottom - 4);
1545
1546   BSOD_PAUSE (bst, 666666);
1547   BSOD_INVERT (bst);
1548   BSOD_LOOP (bst, -3);
1549
1550   XClearWindow (dpy, window);
1551   return bst;
1552 }
1553
1554
1555 static struct bsod_state *
1556 mac1 (Display *dpy, Window window)
1557 {
1558   struct bsod_state *bst = make_bsod_state (dpy, window, "mac1", "Mac1");
1559
1560   Pixmap pixmap = 0;
1561   int pix_w = macbomb_width;
1562   int pix_h = macbomb_height;
1563   int x, y;
1564
1565   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) macbomb_bits,
1566                                         macbomb_width, macbomb_height,
1567                                         bst->fg, bst->bg, bst->xgwa.depth);
1568
1569   x = (bst->xgwa.width - pix_w) / 2;
1570   y = (bst->xgwa.height - pix_h) / 2;
1571   if (y < 0) y = 0;
1572
1573   XClearWindow (dpy, window);
1574   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
1575
1576   return bst;
1577 }
1578
1579
1580 /* This is what kernel panics looked like on MacOS X 10.0 through 10.1.5.
1581    In later releases, it's a graphic of a power button with text in
1582    English, French, German, and Japanese overlayed transparently.
1583  */
1584 static struct bsod_state *
1585 macx_10_0 (Display *dpy, Window window)
1586 {
1587   struct bsod_state *bst = make_bsod_state (dpy, window, "macx", "MacX");
1588
1589   XClearWindow (dpy, window);
1590   XSetForeground (dpy, bst->gc,
1591                   get_pixel_resource (dpy, bst->xgwa.colormap,
1592                                       "macx.textForeground",
1593                                       "MacX.TextForeground"));
1594   XSetBackground (dpy, bst->gc,
1595                   get_pixel_resource (dpy, bst->xgwa.colormap,
1596                                       "macx.textBackground",
1597                                       "MacX.TextBackground"));
1598
1599 # ifdef DO_XPM
1600   {
1601     Pixmap pixmap = 0;
1602     Pixmap mask = 0;
1603     int x, y, pix_w, pix_h;
1604     pixmap = xpm_data_to_pixmap (dpy, window, (char **) happy_mac,
1605                                  &pix_w, &pix_h, &mask);
1606
1607 # ifdef USE_IPHONE
1608     if (pixmap)
1609       {
1610         pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual,
1611                                 bst->xgwa.depth, pixmap, pix_w, pix_h);
1612         mask = double_pixmap (dpy, bst->gc, bst->xgwa.visual,
1613                               1, mask, pix_w, pix_h);
1614         pix_w *= 2;
1615         pix_h *= 2;
1616       }
1617 # endif
1618
1619     x = (bst->xgwa.width - pix_w) / 2;
1620     y = (bst->xgwa.height - pix_h) / 2;
1621     if (y < 0) y = 0;
1622     XSetClipMask (dpy, bst->gc, mask);
1623     XSetClipOrigin (dpy, bst->gc, x, y);
1624     XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
1625     XSetClipMask (dpy, bst->gc, None);
1626     XFreePixmap (dpy, pixmap);
1627   }
1628 #endif /* DO_XPM */
1629
1630   bst->left_margin = 0;
1631   bst->right_margin = 0;
1632   bst->y = bst->font->ascent;
1633   bst->macx_eol_kludge = True;
1634   bst->wrap_p = True;
1635
1636   BSOD_PAUSE (bst, 3000000);
1637   BSOD_TEXT (bst, LEFT,
1638     "panic(cpu 0): Unable to find driver for this platform: "
1639     "\"PowerMac 3,5\".\n"
1640     "\n"
1641     "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
1642     "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
1643     "\n"
1644     "\n"
1645     "\n"
1646     "No debugger configured - dumping debug information\n"
1647     "\n"
1648     "version string : Darwin Kernel Version 1.3:\n"
1649     "Thu Mar  1 06:56:40 PST 2001; root:xnu/xnu-123.5.obj~1/RELEASE_PPC\n"
1650     "\n"
1651     "\n"
1652     "\n"
1653     "\n"
1654     "DBAT0: 00000000 00000000\n"
1655     "DBAT1: 00000000 00000000\n"
1656     "DBAT2: 80001FFE 8000003A\n"
1657     "DBAT3: 90001FFE 9000003A\n"
1658     "MSR=00001030\n"
1659     "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
1660     "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
1661     "\n"
1662     "panic: We are hanging here...\n");
1663
1664   return bst;
1665 }
1666
1667
1668 # ifdef DO_XPM
1669 static struct bsod_state *
1670 macx_10_2 (Display *dpy, Window window, Bool v10_3_p)
1671 {
1672   struct bsod_state *bst = make_bsod_state (dpy, window, "macx", "MacX");
1673
1674   Pixmap pixmap = 0;
1675   int pix_w = 0, pix_h = 0;
1676   int x, y;
1677
1678   pixmap = xpm_data_to_pixmap (dpy, window, 
1679                                (char **) (v10_3_p ? osx_10_3 : osx_10_2),
1680                                &pix_w, &pix_h, 0);
1681   if (! pixmap) abort();
1682
1683 #if 0
1684   if (bst->xgwa.height > 600)   /* scale up the bitmap */
1685     {
1686       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
1687                               pixmap, pix_w, pix_h);
1688       if (! pixmap) abort();
1689       pix_w *= 2;
1690       pix_h *= 2;
1691     }
1692 #endif
1693
1694   BSOD_IMG (bst);
1695   BSOD_PAUSE (bst, 2000000);
1696
1697   bst->pixmap = pixmap;
1698
1699   x = (bst->xgwa.width - pix_w) / 2;
1700   y = ((bst->xgwa.height - pix_h) / 2);
1701   BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, x, y);
1702
1703   return bst;
1704 }
1705 # endif /* DO_XPM */
1706
1707
1708 /* 2006 Mac Mini with MacOS 10.6 failing with a bad boot drive. By jwz.
1709  */
1710 static struct bsod_state *
1711 mac_diskfail (Display *dpy, Window window)
1712 {
1713   struct bsod_state *bst = make_bsod_state (dpy, window, "macdisk", "Mac");
1714   int cw = (bst->font->per_char
1715             ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
1716             : bst->font->min_bounds.width);
1717   int h = bst->font->ascent + bst->font->descent;
1718   int L = (bst->xgwa.width - (cw * 80)) / 2;
1719   int T = (bst->xgwa.height - (h  * 10)) / 2;
1720
1721   unsigned long fg = bst->fg;
1722   unsigned long bg = bst->bg;
1723   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
1724                                           "macx.background",
1725                                           "Mac.Background");
1726   if (L < 0) L = 0;
1727   if (T < 0) T = 0;
1728
1729   bst->wrap_p = True;
1730   bst->scroll_p = True;
1731
1732   BSOD_COLOR(bst, bg2, bg);
1733   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
1734   BSOD_PAUSE (bst, 3000000);
1735
1736   BSOD_COLOR(bst, bg, fg);
1737   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
1738   BSOD_COLOR(bst, fg, bg);
1739
1740   BSOD_MARGINS (bst, L, L);
1741   BSOD_MOVETO (bst, L, T);
1742
1743   BSOD_TEXT (bst, LEFT,
1744              "efiboot loaded from device: Acpi(PNP0A03,0)/Pci*1F|2)/Ata"
1745              "(Primary,Slave)/HD(Part\n"
1746              "2,Sig8997E427-064E-4FE7-8CB9-F27A784B232C)\n"
1747              "boot file path: \\System\\Library\\CoreServices\\boot.efi\n"
1748              ".Loading kernel cache file 'System\\Library\\Caches\\"
1749              "com.apple.kext.caches\\Startup\\\n"
1750              "kernelcache_i386.2A14EC2C'\n"
1751              "Loading 'mach_kernel'...\n"
1752              );
1753   BSOD_CHAR_DELAY (bst, 7000);
1754   BSOD_TEXT (bst, LEFT,
1755              ".....................\n"
1756              );
1757   BSOD_CHAR_DELAY (bst, 0);
1758   BSOD_TEXT (bst, LEFT,
1759              "root device uuid is 'B62181B4-6755-3C27-BFA1-49A0E053DBD6\n"
1760              "Loading drivers...\n"
1761              "Loading System\\Library\\Caches\\com.apple.kext.caches\\"
1762              "Startup\\Extensions.mkext....\n"
1763              );
1764   BSOD_CHAR_DELAY (bst, 7000);
1765   BSOD_TEXT (bst, LEFT,
1766              "..............................................................."
1767              ".................\n"
1768              "..............................................................."
1769              ".................\n"
1770              "..............\n"
1771              );
1772   BSOD_INVERT (bst);
1773   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
1774   BSOD_INVERT (bst);
1775
1776   BSOD_MARGINS (bst, 0, 0);
1777   BSOD_MOVETO (bst, 0, h);
1778
1779   BSOD_CHAR_DELAY (bst, 0);
1780   BSOD_LINE_DELAY (bst, 5000);
1781   BSOD_TEXT (bst, LEFT,
1782              "npvhash=4095\n"
1783              "PRE enabled\n"
1784              "Darwin Kernel Version 10.8.9: Tue Jun  7 16:33:36 PDT 2011;"
1785              " root:xnu-1504.15.3~1/RELEASE_I386\n"
1786              "vm_page_bootstrap: 508036 free pages and 16252 wired pages\n"
1787              "standard timeslicing quantum is 10000 us\n"
1788              "mig_table_max_displ = 73\n"
1789              "AppleACPICPU: ProcessorId=0 LocalApicId=0 Enabled\n"
1790              "AppleACPICPU: ProcessorId=1 LocalApicId=1 Enabled\n"
1791              "calling npo_policy_init for Quarantine\n"
1792              "Security policy loaded: Quaantine policy (Quarantine)\n"
1793              "calling npo_policy_init for Sandbox\n"
1794              "Security policy loaded: Seatbelt sandbox policy (Sandbox)\n"
1795              "calling npo_policy_init for TMSafetyNet\n"
1796              "Security policy loaded: Safety net for Time Machine "
1797              "(TMSafetyNet)\n"
1798              "Copyright (c) 1982, 1986, 1989, 1991, 1993\n"
1799              "The Regents of the University of California. All rights "
1800              "reserved.\n"
1801              "\n"
1802              "MAC Framework successfully initialized\n"
1803              "using 10485 buffer headers and 4096 cluster IO buffer headers\n"
1804              "IOAPIC: Version 0x20 Vectors 64:87\n"
1805              "ACPI: System State [S0 S3 S4 S5] (S3)\n"
1806              "PFM64 0x10000000, 0xf0000000\n"
1807              "[ PCI configuration begin ]\n"
1808              "PCI configuration changed (bridge=1 device=1 cardbus=0)\n"
1809              "[ PCI configuration end, bridges 4 devices 17 ]\n"
1810              "nbinit: done (64 MB memory set for nbuf pool)\n"
1811              "rooting via boot-uuid from /chosen: "
1812              "B62181B4-6755-3C27-BFA1-49A0E053DBD6\n"
1813              "Waiting on <dict ID=\"0\"><key>IOProviderClass</key>"
1814              "<string ID=\"1\">IOResources</string><key>IOResourceMatch</key>"
1815              "<string ID=\"2\">boot-uuid-nedia</string></dict>\n"
1816              "com.apple.AppleFSCCompressionTypeZlib kmod start\n"
1817              "com.apple.AppleFSCCompressionTypeZlib kmod succeeded\n"
1818              "AppleIntelCPUPowerManagementClient: ready\n"
1819              "FireWire (OHCI) Lucent ID 5811  built-in now active, GUID "
1820              "0019e3fffe97f8b4; max speed s400.\n"
1821              "Got boot device = IOService:/AppleACPIPlatformExpert/PCI000/"
1822              "AppleACPIPCI/SATA@1F,2/AppleAHCI/PRI202/IOAHCIDevice@0/"
1823              "AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/"
1824              "IOBlockStorageDriver/ST96812AS Media/IOGUIDPartitionScheme/"
1825              "Customer02\n"
1826              );
1827   BSOD_PAUSE (bst, 1000000);
1828   BSOD_TEXT (bst, LEFT,
1829              "BSD root: Disk0s, major 14, minor 2\n"
1830              "[Bluetooth::CSRHIDTransition] switchtoHCIMode (legacy)\n"
1831              "[Bluetooth::CSRHIDTransition] transition complete.\n"
1832              "CSRUSBBluetoothHCIController::setupHardware super returned 0\n"
1833              );
1834   BSOD_PAUSE (bst, 3000000);
1835   BSOD_TEXT (bst, LEFT,
1836              "disk0s2: I/O error.\n"
1837              "0 [Level 3] [ReadUID 0] [Facility com.apple.system.fs] "
1838              "[ErrType IO] [ErrNo 5] [IOType Read] [PBlkNum 48424] "
1839              "[LBlkNum 1362] [FSLogMsgID 2009724291] [FSLogMsgOrder First]\n"
1840              "0 [Level 3] [ReadUID 0] [Facility com.apple.system.fs] "
1841              "[DevNode root_device] [MountPt /] [FSLogMsgID 2009724291] "
1842              "[FSLogMsgOrder Last]\n"
1843              "panic(cpu 0 caller 0x47f5ad): \"Process 1 exec of /sbin/launchd"
1844              " failed, errno 5\\n\"0/SourceCache/xnu/xnu-1504.15.3/bsd/kern/"
1845              "kern_exec.c:3145\n"
1846              "Debugger called: <panic>\n"
1847              "Backtrace (CPU 0), Frame : Return Address (4 potential args "
1848              "on stack)\n"
1849              "0x34bf3e48 : 0x21b837 (0x5dd7fc 0x34bf3e7c 0x223ce1 0x0)\n"
1850              "0x34bf3e98 : 0x47f5ad (0x5cf950 0x831c08 0x5 0x0)\n"
1851              "0x34bf3ef8 : 0x4696d2 (0x4800d20 0x1fe 0x45a69a0 0x80000001)\n"
1852              "0x34bf3f38 : 0x48fee5 (0x46077a8 0x84baa0 0x34bf3f88 "
1853              "0x34bf3f94)\n"
1854              "0x34bf3f68 : 0x219432 (0x46077a8 0xffffff7f 0x0 0x227c4b)\n"
1855              "0x34bf3fa8 : 0x2aacb4 (0xffffffff 0x1 0x22f8f5 0x227c4b)\n"
1856              "0x34bf3fc8 : 0x2a1976 (0x0 0x0 0x2a17ab 0x4023ef0)\n"
1857              "\n"
1858              "BSD process name corresponding to current thread: init\n"
1859              "\n"
1860              "Mac OS version:\n"
1861              "Not yet set\n"
1862              "\n"
1863              "Kernel version:\n"
1864              "Darwin Kernel version 10.8.0: Tue Jun  7 16:33:36 PDT 2011; "
1865              "root:xnu-1504.15-3~1/RELEASE_I386\n"
1866              "System model name: Macmini1,1 (Mac-F4208EC0)\n"
1867              "\n"
1868              "System uptime in nanoseconds: 13239332027\n"
1869              );
1870   BSOD_CURSOR (bst, CURSOR_BLOCK, 500000, 999999);
1871
1872   XClearWindow (dpy, window);
1873
1874   return bst;
1875 }
1876
1877
1878
1879 static struct bsod_state *
1880 macx (Display *dpy, Window window)
1881 {
1882 # ifdef DO_XPM
1883   switch (random() % 4) {
1884   case 0: return macx_10_0 (dpy, window);        break;
1885   case 1: return macx_10_2 (dpy, window, False); break;
1886   case 2: return macx_10_2 (dpy, window, True);  break;
1887   case 3: return mac_diskfail (dpy, window); break;
1888   default: abort();
1889   }
1890 # else  /* !DO_XPM */
1891   switch (random() % 2) {
1892   case 0:  return macx_10_0 (dpy, window);    break;
1893   default: return mac_diskfail (dpy, window); break;
1894   }
1895 # endif /* !DO_XPM */
1896 }
1897
1898
1899 #ifndef HAVE_COCOA /* #### I have no idea how to implement this without
1900                            real plane-masks.  I don't think it would look
1901                            right if done with alpha-transparency... */
1902 /* blit damage
1903  *
1904  * by Martin Pool <mbp@samba.org>, Feb 2000.
1905  *
1906  * This is meant to look like the preferred failure mode of NCD
1907  * Xterms.  The parameters for choosing what to copy where might not
1908  * be quite right, but it looks about ugly enough.
1909  */
1910 static struct bsod_state *
1911 blitdamage (Display *dpy, Window window)
1912 {
1913   struct bsod_state *bst = 
1914     make_bsod_state (dpy, window, "blitdamage", "BlitDamage");
1915
1916   int i;
1917   int delta_x = 0, delta_y = 0;
1918   int w, h;
1919   int chunk_h, chunk_w;
1920   int steps;
1921   long gc_mask = 0;
1922   int src_x, src_y;
1923   int x, y;
1924   
1925   w = bst->xgwa.width;
1926   h = bst->xgwa.height;
1927
1928   gc_mask = GCForeground;
1929   
1930   XSetPlaneMask (dpy, bst->gc, random());
1931
1932   steps = 50;
1933   chunk_w = w / (random() % 1 + 1);
1934   chunk_h = h / (random() % 1 + 1);
1935   if (random() & 0x1000) 
1936     delta_y = random() % 600;
1937   if (!delta_y || (random() & 0x2000))
1938     delta_x = random() % 600;
1939   src_x = 0; 
1940   src_y = 0; 
1941   x = 0;
1942   y = 0;
1943   
1944   BSOD_IMG (bst);
1945   for (i = 0; i < steps; i++) {
1946     if (x + chunk_w > w) 
1947       x -= w;
1948     else
1949       x += delta_x;
1950     
1951     if (y + chunk_h > h)
1952       y -= h;
1953     else
1954       y += delta_y;
1955     
1956     BSOD_COPY (bst, src_x, src_y, chunk_w, chunk_h, x, y);
1957     BSOD_PAUSE (bst, 1000);
1958   }
1959
1960   return bst;
1961 }
1962 #endif /* !HAVE_COCOA */
1963
1964
1965 /*
1966  * OS/2 panics, by Knut St. Osmundsen <bird-xscreensaver@anduin.net>
1967  *
1968  * All but one messages are real ones, some are from my test machines
1969  * and system dumps, others are reconstructed from google results.
1970  * Please, don't be to hard if the formatting of the earlier systems
1971  * aren't 100% correct.
1972  */
1973 static struct bsod_state *
1974 os2 (Display *dpy, Window window)
1975 {
1976   struct bsod_state *bst = make_bsod_state (dpy, window, "os2", "OS2");
1977
1978   __extension__
1979   static const char * const os2_panics[] =
1980     { /* OS/2 2.0 trap - details are bogus (CR0++). */
1981       "TRAP 0002       ERRCD=0000  ERACC=****  ERLIM=********\n"
1982       "EAX=7d240a58  EBX=ff202fdc  ECX=00064423  EDX=00003624\n"
1983       "ESI=fff3272c  EDI=7d240004  EBP=00004a44  FLG=00003202\n"
1984       "CS:EIP=0160:fff702a6  CSACC=c09d  CSLIM=ffffffff\n"
1985       "SS:ESP=0030:00004a38  SSACC=1097  SSLIM=00003fff\n"
1986       "DS=0158  DSACC=c0f3  DSLIM=ffffffff  CR0=fffffffb\n"
1987       "ES=0158  ESACC=c0f3  ESLIM=ffffffff  CR2=1a060014\n"
1988       "FS=0000  FSACC=****  FSLIM=********\n"
1989       "GS=0000  GSACC=****  GSLIM=********\n"
1990       "\n"
1991       "The system detected an internal processing error\n"
1992       "at location ##0160:fff6453f - 000d:a53f\n"
1993       "60000, 9084\n"
1994       "\n"
1995       "038600d1\n"
1996       "Internal revision 6.307, 92/03/01\n"
1997       "\n",
1998
1999       /* warp 3 (early) */
2000       "TRAP 000e       ERRCD=0000  ERACC=****  ERLIM=********\n"
2001       "EAX=ff050c20  EBX=000000bb  ECX=ffff00c1  EDx=fff379b8\n"
2002       "ESI=ffe55a3c  EDI=00000000  EBP=00004eb8  FLG=00013282\n"
2003       "CS:EIP=0160:fff8dbb8  CSACC=c09b  CSLIM=ffffffff\n"
2004       "SS:EIP=0030:00004eb4  SSACC=1097  SSLIM=00003fff\n"
2005       "DS=0158  DSACC=c0f3  DSLIM=ffffffff  CR0=8001001b\n"
2006       "ES=0158  DSACC=c0f3  DSLIM=ffffffff  CR2=000000c7\n"
2007       "FS=0000  FSACC=****  FSLIM=********\n"
2008       "GS=0000  GSACC=****  GSLIM=********\n"
2009       "\n"
2010       "The system detected an internal processing error\n"
2011       "at location ##0160:fff66bf0 - 000d:9bf0.\n"
2012       "60000, 9084\n"
2013       "\n"
2014       "048600b4\n"
2015       "Internal revision 8.125, 94/02/16\n"
2016       "\n"
2017       "The system is stopped.  Record the location number of the error\n"
2018       "and contact your service representative.\n",
2019
2020       /* warp 3 */
2021       "TRAP 000e       ERRCD=0002  ERACC=****  ERLIM=********\n"
2022       "EAX=00000000  EBX=fdef1e0c  ECX=00003824  EDX=0000edf9\n"
2023       "ESI=fdf30e80  EDI=fc8b0000  EBP=00005658  FLG=00012246\n"
2024       "CS:EIP=0160:fff8ada3  CSACC=c09b  CSLIM=ffffffff\n"
2025       "SS:ESP=0030:000055d4  SSACC=1097  SSLIM=0000480f\n"
2026       "DS=0158  DSACC=c093  DSLIM=ffffffff  CR0=8001001b\n"
2027       "ES=0158  ESACC=c093  ESLIM=ffffffff  CR2=fc8b0000\n"
2028       "FS=03b8  FSACC=0093  FSLIM=00000023\n"
2029       "GS=0000  GSACC=****  GSLIM=********\n"
2030       "\n"
2031       "The system detected an internal processing error\n"
2032       "at location ##0160:fff5c364 - 000d:a364.\n"
2033       "60000, 9084\n"
2034       "\n"
2035       "05860526\n"
2036       "Internal revision 8200,94/11/07\n"
2037       "\n"
2038       "The system is stopped. Record all of the above information and\n"
2039       "contact your service representative.\n",
2040
2041       /* warp 3 (late) */
2042       "TRAP 000d       ERRCD=2200  ERACC=1092  ERLIM=00010fff\n"
2043       "EAX=0000802e  EBX=fff001c8  ECX=9bd80000  EDX=00000000\n"
2044       "ESI=fff09bd8  EDI=fdeb001b  EBP=00000000  FLG=00012012\n"
2045       "CS:EIP=0168:fff480a2  CSACC=c09b  CSLIM=ffffffff\n"
2046       "SS:ESP=00e8:00001f32  SSACC=0093  SSLIM=00001fff\n"
2047       "DS=0940  DSACC=0093  DSLIM=00000397  CR0=8001001b\n"
2048       "ES=00e8  ESACC=0093  ESLIM=00001fff  CR2=15760008\n"
2049       "FS=0000  FSACC=****  FSLIM=****\n"
2050       "GS=0000  GSACC=****  GSLIM=****\n"
2051       "\n"
2052       "The system detected an internal processing error\n"
2053       "at location ##0168:fff4b06e - 000e:c06e\n"
2054       "60000, 9084\n"
2055       "\n"
2056       "06860652\n"
2057       "Internal revision 8.259_uni,98/01/07\n"
2058       "\n"
2059       "The system is stopped. Record all of the above information and\n"
2060       "contact your service representative.\n",
2061
2062       /* Warp 4.52+ - the official r0trap.exe from the debugging classes */
2063       "Exception in module: OS2KRNL\n"
2064       "TRAP 000e       ERRCD=0002  ERACC=****  ERLIM=********\n"
2065       "EAX=00000001  EBX=80010002  ECX=ffed4638  EDX=0003f17b\n"
2066       "ESI=00000001  EDI=00000002  EBP=00005408  FLG=00012202\n"
2067       "CS:EIP=0168:fff3cd2e  CSACC=c09b  CSLIM=ffffffff\n"
2068       "SS:ESP=0030:000053ec  SSACC=1097  SSLIM=000044ff\n"
2069       "DS=0160  DSACC=c093  DSLIM=ffffffff  CR0=8001001b\n"
2070       "ES=0160  ESACC=c093  ESLIM=ffffffff  CR2=00000001\n"
2071       "FS=0000  FSACC=****  FSLIM=********\n"
2072       "GS=0000  GSACC=****  GSLIM=********\n"
2073       "\n"
2074       "The system detected an internal processing error at\n"
2075       "location ##0168:fff1e3f3 - 000e:c3f3.\n"
2076       "60000, 9084\n"
2077       "\n"
2078       "068606a0\n"
2079       "Internal revision 14.097_UNI\n"
2080       "\n"
2081       "The system is stopped. Record all of the above information and\n"
2082       "contact your service representative.\n",
2083
2084       /* Warp 4.52+, typical JFS problem. */
2085       "Exeption in module: JFS\n"
2086       "TRAP 0003       ERRCD=0000  ERACC=****  ERLIM=********\n"
2087       "EAX=00000000  EBX=ffffff05  ECX=00000001  EDX=f5cd8010\n"
2088       "ESI=000000e6  EDI=000000e7  EBP=f9c7378e  FLG=00002296\n"
2089       "CS:EIP=0168:f8df3250  CSACC=c09b  CSLIM=ffffffff\n"
2090       "SS:ESP=1550:fdc73778  SSACC=c093  SSLIM=ffffffff\n"
2091       "DS=0160  DSACC=c093  DSLIM=ffffffff  CR0=80010016\n"
2092       "ES=0160  ESACC=c093  DSLIM=ffffffff  CR2=05318000\n"
2093       "FS=03c0  FSACC=0093  DSLIM=00000023\n"
2094       "GS=0160  GSACC=c093  DSLIM=ffffffff\n"
2095       "\n"
2096       "The system detected an internal processing error\n"
2097       "at location ##0168:fff1e2ab - 000e:c2ab.\n"
2098       "60000, 9084\n"
2099       "\n"
2100       "07860695\n"
2101       "\n"
2102       "Internal revision 14.100c_UNI\n"
2103       "\n"
2104       "The system is stopped. Record all of the above information and\n"
2105       "contact your service representative.\n"
2106     };
2107
2108   BSOD_TEXT (bst, LEFT, os2_panics[random() % countof(os2_panics)]);
2109   BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999);
2110
2111   XClearWindow (dpy, window);
2112   return bst;
2113 }
2114
2115
2116 /* SPARC Solaris panic. Should look pretty authentic on Solaris boxes.
2117  * Anton Solovyev <solovam@earthlink.net>
2118  */ 
2119 static struct bsod_state *
2120 sparc_solaris (Display *dpy, Window window)
2121 {
2122   struct bsod_state *bst = make_bsod_state (dpy, window, "solaris", "Solaris");
2123   int i;
2124
2125   bst->scroll_p = True;
2126   bst->wrap_p = True;
2127   bst->left_margin = bst->right_margin = bst->xgwa.width  * 0.07;
2128   bst->top_margin = bst->bottom_margin = bst->xgwa.height * 0.07;
2129   bst->y = bst->top_margin + bst->font->ascent;
2130
2131   BSOD_IMG (bst);
2132   BSOD_PAUSE (bst, 3000000);
2133
2134   BSOD_INVERT(bst);
2135   BSOD_RECT (bst, True, 
2136              bst->left_margin, bst->top_margin,
2137              bst->xgwa.width - bst->left_margin - bst->right_margin,
2138              bst->xgwa.height - bst->top_margin - bst->bottom_margin);
2139   BSOD_INVERT(bst);
2140
2141   BSOD_TEXT (bst, LEFT,
2142     "BAD TRAP: cpu=0 type=0x31 rp=0x2a10043b5e0 addr=0xf3880 mmu_fsr=0x0\n"
2143     "BAD TRAP occurred in module \"unix\" due to an illegal access to a"
2144     " user address.\n"
2145     "adb: trap type = 0x31\n"
2146     "addr=0xf3880\n"
2147     "pid=307, pc=0x100306e4, sp=0x2a10043ae81, tstate=0x4480001602,"
2148     " context=0x87f\n"
2149     "g1-g7: 1045b000, 32f, 10079440, 180, 300000ebde8, 0, 30000953a20\n"
2150     "Begin traceback... sp = 2a10043ae81\n"
2151     "Called from 100bd060, fp=2a10043af31, args=f3700 300008cc988 f3880 0"
2152     " 1 300000ebde0.\n"
2153     "Called from 101fe1bc, fp=2a10043b011, args=3000045a240 104465a0"
2154     " 300008e47d0 300008e48fa 300008ae350 300008ae410\n"
2155     "Called from 1007c520, fp=2a10043b0c1, args=300008e4878 300003596e8 0"
2156     " 3000045a320 0 3000045a220\n"
2157     "Called from 1007c498, fp=2a10043b171, args=1045a000 300007847f0 20"
2158     " 3000045a240 1 0\n"
2159     "Called from 1007972c, fp=2a10043b221, args=1 300009517c0 30000951e58 1"
2160     " 300007847f0 0\n"
2161     "Called from 10031e10, fp=2a10043b2d1, args=3000095b0c8 0 300009396a8"
2162     " 30000953a20 0 1\n"
2163     "Called from 10000bdd8, fp=ffffffff7ffff1c1, args=0 57 100131480"
2164     " 100131480 10012a6e0 0\n"
2165     "End traceback...\n"
2166     "panic[cpu0]/thread=30000953a20: trap\n"
2167     "syncing file systems...");
2168
2169   BSOD_PAUSE (bst, 3000000);
2170
2171   BSOD_TEXT (bst, LEFT, " 1 done\n");
2172   BSOD_TEXT (bst, LEFT, "dumping to /dev/dsk/c0t0d0s3, offset 26935296\n");
2173   BSOD_PAUSE (bst, 2000000);
2174
2175
2176   for (i = 1; i <= 100; ++i)
2177     {
2178       char buf[100];
2179       sprintf (buf, "\b\b\b\b\b\b\b\b\b\b\b%3d%% done", i);
2180       BSOD_TEXT (bst, LEFT, buf);
2181       BSOD_PAUSE (bst, 100000);
2182     }
2183
2184   BSOD_TEXT (bst, LEFT,
2185     ": 2803 pages dumped, compression ratio 2.88, dump succeeded\n");
2186   BSOD_PAUSE (bst, 2000000);
2187
2188   BSOD_TEXT (bst, LEFT,
2189     "rebooting...\n"
2190     "Resetting ...");
2191
2192   return bst;
2193 }
2194
2195
2196 /* Linux panic and fsck, by jwz
2197  */
2198 static struct bsod_state *
2199 linux_fsck (Display *dpy, Window window)
2200 {
2201   struct bsod_state *bst = make_bsod_state (dpy, window, "linux", "Linux");
2202
2203   int i;
2204   const char *sysname;
2205   char buf[1024];
2206
2207   const char *linux_panic[] = {
2208    " kernel: Unable to handle kernel paging request at virtual "
2209      "address 0000f0ad\n",
2210    " kernel:  printing eip:\n",
2211    " kernel: c01becd7\n",
2212    " kernel: *pde = 00000000\n",
2213    " kernel: Oops: 0000\n",
2214    " kernel: CPU:    0\n",
2215    " kernel: EIP:    0010:[<c01becd7>]    Tainted: P \n",
2216    " kernel: EFLAGS: 00010286\n",
2217    " kernel: eax: 0000ff00   ebx: ca6b7e00   ecx: ce1d7a60   edx: ce1d7a60\n",
2218    " kernel: esi: ca6b7ebc   edi: 00030000   ebp: d3655ca0   esp: ca6b7e5c\n",
2219    " kernel: ds: 0018   es: 0018   ss: 0018\n",
2220    " kernel: Process crond (pid: 1189, stackpage=ca6b7000)\n",
2221    " kernel: Stack: d3655ca0 ca6b7ebc 00030054 ca6b7e7c c01c1e5b "
2222        "00000287 00000020 c01c1fbf \n",
2223    "",
2224    " kernel:        00005a36 000000dc 000001f4 00000000 00000000 "
2225        "ce046d40 00000001 00000000 \n",
2226    "", "", "",
2227    " kernel:        ffffffff d3655ca0 d3655b80 00030054 c01bef93 "
2228        "d3655ca0 ca6b7ebc 00030054 \n",
2229    "", "", "",
2230    " kernel: Call Trace:    [<c01c1e5b>] [<c01c1fbf>] [<c01bef93>] "
2231        "[<c01bf02b>] [<c0134c4f>]\n",
2232    "", "", "",
2233    " kernel:   [<c0142562>] [<c0114f8c>] [<c0134de3>] [<c010891b>]\n",
2234    " kernel: \n",
2235    " kernel: Code: 2a 00 75 08 8b 44 24 2c 85 c0 74 0c 8b 44 24 58 83 48 18 "
2236       "08 \n",
2237    0
2238   };
2239
2240   bst->scroll_p = True;
2241   bst->wrap_p = True;
2242   bst->left_margin = bst->right_margin = 10;
2243   bst->top_margin = bst->bottom_margin = 10;
2244
2245   sysname = "linux";
2246 # ifdef HAVE_UNAME
2247   {
2248     struct utsname uts;
2249     char *s;
2250     if (uname (&uts) >= 0)
2251       sysname = uts.nodename;
2252     s = strchr (sysname, '.');
2253     if (s) *s = 0;
2254   }
2255 # endif /* !HAVE_UNAME */
2256
2257
2258   BSOD_TEXT (bst, LEFT, "waiting for X server to shut down ");
2259   BSOD_PAUSE (bst, 100000);
2260   BSOD_TEXT (bst, LEFT,
2261              "XIO:  fatal IO error 2 (broken pipe) on X server \":0.0\"\n"
2262              "        after 339471 requests (339471 known processed) "
2263              "with 0 events remaining\n");
2264   BSOD_CHAR_DELAY (bst, 300000);
2265   BSOD_TEXT (bst, LEFT, ".........\n");
2266   BSOD_CHAR_DELAY (bst, 0);
2267   BSOD_TEXT (bst, LEFT, 
2268              "xinit:  X server slow to shut down, sending KILL signal.\n"
2269              "waiting for server to die ");
2270   BSOD_CHAR_DELAY (bst, 300000);
2271   BSOD_TEXT (bst, LEFT, "...\n");
2272   BSOD_CHAR_DELAY (bst, 0);
2273   BSOD_TEXT (bst, LEFT, "xinit:  Can't kill server\n");
2274   BSOD_PAUSE (bst, 2000000);
2275
2276   sprintf (buf, "\n%s Login: ", sysname);
2277   BSOD_TEXT (bst, LEFT, buf);
2278   BSOD_PAUSE (bst, 1000000);
2279   BSOD_TEXT (bst, LEFT,
2280     "\n\n"
2281     "Parallelizing fsck version 1.22 (22-Jun-2001)\n"
2282     "e2fsck 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09\n"
2283     "Warning!  /dev/hda1 is mounted.\n"
2284     "/dev/hda1 contains a file system with errors, check forced.\n");
2285   BSOD_PAUSE (bst, 1000000);
2286
2287   if (0 == random() % 2)
2288     BSOD_TEXT (bst, LEFT,
2289      "Couldn't find ext2 superblock, trying backup blocks...\n"
2290      "The filesystem size (according to the superblock) is 3644739 blocks\n"
2291      "The physical size of the device is 3636706 blocks\n"
2292      "Either the superblock or the partition table is likely to be corrupt!\n"
2293      "Abort<y>? no\n");
2294   BSOD_PAUSE (bst, 1000000);
2295
2296  AGAIN:
2297
2298   BSOD_TEXT (bst, LEFT, "Pass 1: Checking inodes, blocks, and sizes\n");
2299   BSOD_PAUSE (bst, 2000000);
2300
2301   i = (random() % 60) - 20;
2302   while (--i > 0)
2303     {
2304       int b = random() % 0xFFFF;
2305       sprintf (buf, "Deleted inode %d has zero dtime.  Fix<y>? yes\n\n", b);
2306       BSOD_TEXT (bst, LEFT, buf);
2307       BSOD_PAUSE (bst, 1000);
2308     }
2309
2310   i = (random() % 40) - 10;
2311   if (i > 0)
2312     {
2313       int g = random() % 0xFFFF;
2314       int b = random() % 0xFFFFFFF;
2315
2316       BSOD_PAUSE (bst, 1000000);
2317
2318       sprintf (buf, "Warning: Group %d's copy of the group descriptors "
2319                "has a bad block (%d).\n", g, b);
2320       BSOD_TEXT (bst, LEFT, buf);
2321
2322       b = random() % 0x3FFFFF;
2323       while (--i > 0)
2324         {
2325           b += random() % 0xFFFF;
2326           sprintf (buf,
2327                    "Error reading block %d (Attempt to read block "
2328                    "from filesystem resulted in short read) while doing "
2329                    "inode scan.  Ignore error<y>?",
2330                    b);
2331           BSOD_TEXT (bst, LEFT, buf);
2332           BSOD_PAUSE (bst, 10000);
2333           BSOD_TEXT (bst, LEFT, " yes\n\n");
2334         }
2335     }
2336
2337   if (0 == (random() % 10))
2338     {
2339       BSOD_PAUSE (bst, 1000000);
2340
2341       i = 3 + (random() % 10);
2342       while (--i > 0)
2343         {
2344           BSOD_TEXT (bst, LEFT,
2345                      "Could not allocate 256 block(s) for inode table: "
2346                      "No space left on device\n");
2347           BSOD_PAUSE (bst, 1000);
2348         }
2349       BSOD_TEXT (bst, LEFT, "Restarting e2fsck from the beginning...\n");
2350       BSOD_PAUSE (bst, 2000000);
2351
2352       goto AGAIN;
2353     }
2354
2355   i = (random() % 20) - 5;
2356
2357   if (i > 0)
2358     BSOD_PAUSE (bst, 1000000);
2359
2360   while (--i > 0)
2361     {
2362       int j = 5 + (random() % 10);
2363       int w = random() % 4;
2364
2365       while (--j > 0)
2366         {
2367           int b = random() % 0xFFFFF;
2368           int g = random() % 0xFFF;
2369
2370           if (0 == (random() % 10))
2371             b = 0;
2372           else if (0 == (random() % 10))
2373             b = -1;
2374
2375           if (w == 0)
2376             sprintf (buf,
2377                      "Inode table for group %d not in group.  (block %d)\n"
2378                      "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
2379                      "Relocate<y>?",
2380                      g, b);
2381           else if (w == 1)
2382             sprintf (buf,
2383                      "Block bitmap for group %d not in group.  (block %d)\n"
2384                      "Relocate<y>?",
2385                      g, b);
2386           else if (w == 2)
2387             sprintf (buf,
2388                      "Inode bitmap %d for group %d not in group.\n"
2389                      "Continue<y>?",
2390                      b, g);
2391           else /* if (w == 3) */
2392             sprintf (buf,
2393                      "Bad block %d in group %d's inode table.\n"
2394                      "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
2395                      "Relocate<y>?",
2396                      b, g);
2397
2398           BSOD_TEXT (bst, LEFT, buf);
2399           BSOD_TEXT (bst, LEFT, " yes\n\n");
2400           BSOD_PAUSE (bst, 1000);
2401         }
2402     }
2403
2404
2405   if (0 == random() % 10) goto PANIC;
2406   BSOD_TEXT (bst, LEFT, "Pass 2: Checking directory structure\n");
2407   BSOD_PAUSE (bst, 2000000);
2408
2409   i = (random() % 20) - 5;
2410   while (--i > 0)
2411     {
2412       int n = random() % 0xFFFFF;
2413       int o = random() % 0xFFF;
2414       sprintf (buf, "Directory inode %d, block 0, offset %d: "
2415                "directory corrupted\n"
2416                "Salvage<y>? ",
2417                n, o);
2418       BSOD_TEXT (bst, LEFT, buf);
2419       BSOD_PAUSE (bst, 1000);
2420       BSOD_TEXT (bst, LEFT, " yes\n\n");
2421
2422       if (0 == (random() % 100))
2423         {
2424           sprintf (buf, "Missing '.' in directory inode %d.\nFix<y>?", n);
2425           BSOD_TEXT (bst, LEFT, buf);
2426           BSOD_PAUSE (bst, 1000);
2427           BSOD_TEXT (bst, LEFT, " yes\n\n");
2428         }
2429     }
2430
2431   if (0 == random() % 10)
2432     goto PANIC;
2433
2434   BSOD_TEXT (bst, LEFT, 
2435              "Pass 3: Checking directory connectivity\n"
2436              "/lost+found not found.  Create? yes\n");
2437   BSOD_PAUSE (bst, 2000000);
2438
2439   /* Unconnected directory inode 4949 (/var/spool/squid/06/???)
2440      Connect to /lost+found<y>? yes
2441
2442      '..' in /var/spool/squid/06/08 (20351) is <The NULL inode> (0), should be 
2443      /var/spool/squid/06 (20350).
2444      Fix<y>? yes
2445
2446      Unconnected directory inode 128337 (/var/spool/squid/06/???)
2447      Connect to /lost+found<y>? yes
2448    */
2449
2450
2451   if (0 == random() % 10) goto PANIC;
2452   BSOD_TEXT (bst, LEFT,  "Pass 4: Checking reference counts\n");
2453   BSOD_PAUSE (bst, 2000000);
2454
2455   /* Inode 2 ref count is 19, should be 20.  Fix<y>? yes
2456
2457      Inode 4949 ref count is 3, should be 2.  Fix<y>? yes
2458
2459         ...
2460
2461      Inode 128336 ref count is 3, should be 2.  Fix<y>? yes
2462
2463      Inode 128337 ref count is 3, should be 2.  Fix<y>? yes
2464
2465    */
2466
2467
2468   if (0 == random() % 10) goto PANIC;
2469   BSOD_TEXT (bst, LEFT,  "Pass 5: Checking group summary information\n");
2470   BSOD_PAUSE (bst, 2000000);
2471
2472   i = (random() % 200) - 50;
2473   if (i > 0)
2474     {
2475       BSOD_TEXT (bst, LEFT,  "Block bitmap differences: ");
2476       while (--i > 0)
2477         {
2478           sprintf (buf, " %d", -(random() % 0xFFF));
2479           BSOD_TEXT (bst, LEFT, buf);
2480           BSOD_PAUSE (bst, 1000);
2481         }
2482       BSOD_TEXT (bst, LEFT, "\nFix? yes\n\n");
2483     }
2484
2485
2486   i = (random() % 100) - 50;
2487   if (i > 0)
2488     {
2489       BSOD_TEXT (bst, LEFT,  "Inode bitmap differences: ");
2490       while (--i > 0)
2491         {
2492           sprintf (buf, " %d", -(random() % 0xFFF));
2493           BSOD_TEXT (bst, LEFT, buf);
2494           BSOD_PAUSE (bst, 1000);
2495         }
2496       BSOD_TEXT (bst, LEFT,  "\nFix? yes\n\n");
2497     }
2498
2499   i = (random() % 20) - 5;
2500   while (--i > 0)
2501     {
2502       int g = random() % 0xFFFF;
2503       int c = random() % 0xFFFF;
2504       sprintf (buf,
2505                "Free blocks count wrong for group #0 (%d, counted=%d).\nFix? ",
2506                g, c);
2507       BSOD_TEXT (bst, LEFT, buf);
2508       BSOD_PAUSE (bst, 1000);
2509       BSOD_TEXT (bst, LEFT,  " yes\n\n");
2510     }
2511
2512  PANIC:
2513
2514   i = 0;
2515   BSOD_TEXT (bst, LEFT,  "\n\n");
2516   while (linux_panic[i])
2517     {
2518       time_t t = time ((time_t *) 0);
2519       struct tm *tm = localtime (&t);
2520       char prefix[100];
2521
2522       if (*linux_panic[i])
2523         {
2524           strftime (prefix, sizeof(prefix)-1, "%b %d %H:%M:%S ", tm);
2525           BSOD_TEXT (bst, LEFT,  prefix);
2526           BSOD_TEXT (bst, LEFT,  sysname);
2527           BSOD_TEXT (bst, LEFT,  linux_panic[i]);
2528           BSOD_PAUSE (bst, 1000);
2529         }
2530       else
2531         BSOD_PAUSE (bst, 300000);
2532
2533       i++;
2534     }
2535   BSOD_PAUSE (bst, 4000000);
2536
2537   XClearWindow(dpy, window);
2538   return bst;
2539 }
2540
2541
2542 /*
2543  * Linux (hppa) panic, by Stuart Brady <sdbrady@ntlworld.com>
2544  * Output courtesy of M. Grabert
2545  */
2546 static struct bsod_state *
2547 hppa_linux (Display *dpy, Window window)
2548 {
2549   struct bsod_state *bst = 
2550     make_bsod_state (dpy, window, "hppalinux", "HPPALinux");
2551
2552   int i = 0;
2553   const char *release, *sysname, *gccversion, *version;
2554   long int linedelay = 0;
2555
2556   __extension__
2557   struct { long int delay; const char *string; } linux_panic[] =
2558     {{ 0, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
2559           "\n\n\n\n\n\n\n\n\n\n\n\n\n" },
2560      { 0, "Linux version %s (root@%s) (gcc version %s) %s\n" },
2561      { 4000, "FP[0] enabled: Rev 1 Model 16\n" },
2562      { 10, "The 32-bit Kernel has started...\n" },
2563      { -1, "Determining PDC firmware type: System Map.\n" },
2564      { -1, "model 00005bb0 00000481 00000000 00000002 7778df9f 100000f0 "
2565            "00000008 000000b2 000000b2\n" },
2566      { -1, "vers  00000203\n" },
2567      { -1, "CPUID vers 17 rev 7 (0x00000227)\n" },
2568      { -1, "capabilities 0x3\n" },
2569      { -1, "model 9000/785/C3000\n" },
2570      { -1, "Total Memory: 1024 Mb\n" },
2571      { -1, "On node 0 totalpages: 262144\n" },
2572      { -1, "  DMA zone: 262144 pages, LIFO batch:16\n" },
2573      { -1, "  Normal zone: 0 pages, LIFO batch:1\n" },
2574      { -1, "  HighMem zone: 0 pages, LIFO batch:1\n" },
2575      { -1, "LCD display at f05d0008,f05d0000 registered\n" },
2576      { -1, "Building zonelist for node : 0\n" },
2577      { -1, "Kernel command line: ide=nodma root=/dev/sda3 HOME=/ ip=off "
2578            "console=ttyS0 TERM=vt102 palo_kernel=2/vmlinux-2.6\n" },
2579      { -1, "ide_setup: ide=nodmaIDE: Prevented DMA\n" },
2580      { -1, "PID hash table entries: 16 (order 4: 128 bytes)\n" },
2581      {500, "Console: colour dummy device 160x64\n" },
2582      { 10, "Memory: 1034036k available\n" },
2583      { -1, "Calibrating delay loop... 796.67 BogoMIPS\n" },
2584      { -1, "Dentry cache hash table entries: 131072 (order: 7, 524288 "
2585            "bytes)\n" },
2586      { -1, "Inode-cache hash table entries: 65536 (order: 6, 262144 "
2587            "bytes)\n" },
2588      { -1, "Mount-cache hash table entries: 512 (order: 0, 4096 bytes)\n" },
2589      { -1, "POSIX conformance testing by UNIFIX\n" },
2590      { -1, "NET: Registered protocol family 16\n" },
2591      { 100, "Searching for devices...\n" },
2592      { 25, "Found devices:\n" },
2593      { 10, "1. Astro BC Runway Port at 0xfed00000 [10] "
2594            "{ 12, 0x0, 0x582, 0x0000b }\n" },
2595      { -1, "2. Elroy PCI Bridge at 0xfed30000 [10/0] "
2596            "{ 13, 0x0, 0x782, 0x0000a }\n" },
2597      { -1, "3. Elroy PCI Bridge at 0xfed32000 [10/1] "
2598            "{ 13, 0x0, 0x782, 0x0000a }\n" },
2599      { -1, "4. Elroy PCI Bridge at 0xfed38000 [10/4] "
2600            "{ 13, 0x0, 0x782, 0x0000a }\n" },
2601      { -1, "5. Elroy PCI Bridge at 0xfed3c000 [10/6] "
2602            "{ 13, 0x0, 0x782, 0x0000a }\n" },
2603      { -1, "6. AllegroHigh W at 0xfffa0000 [32] "
2604            "{ 0, 0x0, 0x5bb, 0x00004 }\n" },
2605      { -1, "7. Memory at 0xfed10200 [49] { 1, 0x0, 0x086, 0x00009 }\n" },
2606      { -1, "CPU(s): 1 x PA8500 (PCX-W) at 400.000000 MHz\n" },
2607      { -1, "SBA found Astro 2.1 at 0xfed00000\n" },
2608      { -1, "lba version TR2.1 (0x2) found at 0xfed30000\n" },
2609      { -1, "lba version TR2.1 (0x2) found at 0xfed32000\n" },
2610      { -1, "lba version TR2.1 (0x2) found at 0xfed38000\n" },
2611      { -1, "lba version TR2.1 (0x2) found at 0xfed3c000\n" },
2612      { 100, "SCSI subsystem initialized\n" },
2613      { 10, "drivers/usb/core/usb.c: registered new driver usbfs\n" },
2614      { -1, "drivers/usb/core/usb.c: registered new driver hub\n" },
2615      { -1, "ikconfig 0.7 with /proc/config*\n" },
2616      { -1, "Initializing Cryptographic API\n" },
2617      { 250, "SuperIO: probe of 0000:00:0e.0 failed with error -1\n" },
2618      { 20, "SuperIO: Found NS87560 Legacy I/O device at 0000:00:0e.1 "
2619            "(IRQ 64)\n" },
2620      { -1, "SuperIO: Serial port 1 at 0x3f8\n" },
2621      { -1, "SuperIO: Serial port 2 at 0x2f8\n" },
2622      { -1, "SuperIO: Parallel port at 0x378\n" },
2623      { -1, "SuperIO: Floppy controller at 0x3f0\n" },
2624      { -1, "SuperIO: ACPI at 0x7e0\n" },
2625      { -1, "SuperIO: USB regulator enabled\n" },
2626      { -1, "SuperIO: probe of 0000:00:0e.2 failed with error -1\n" },
2627      { -1, "Soft power switch enabled, polling @ 0xf0400804.\n" },
2628      { -1, "pty: 256 Unix98 ptys configured\n" },
2629      { -1, "Generic RTC Driver v1.07\n" },
2630      { -1, "Serial: 8250/16550 driver $Revision: 1.98 $ 13 ports, "
2631            "IRQ sharing disabled\n" },
2632      { -1, "ttyS0 at I/O 0x3f8 (irq = 0) is a 16550A\n" },
2633      { -1, "ttyS1 at I/O 0x2f8 (irq = 0) is a 16550A\n" },
2634      { -1, "Linux Tulip driver version 1.1.13 (May 11, 2002)\n" },
2635      { 150, "tulip0: no phy info, aborting mtable build\n" },
2636      { 10, "tulip0:  MII transceiver #1 config 1000 status 782d "
2637            "advertising 01e1.\n" },
2638      { -1, "eth0: Digital DS21143 Tulip rev 65 at 0xf4008000, "
2639            "00:10:83:F9:B4:34, IRQ 66.\n" },
2640      { -1, "Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2\n" },
2641      { -1, "ide: Assuming 33MHz system bus speed for PIO modes; "
2642            "override with idebus=xx\n" },
2643      { 100, "SiI680: IDE controller at PCI slot 0000:01:06.0\n" },
2644      { 10, "SiI680: chipset revision 2\n" },
2645      { -1, "SiI680: BASE CLOCK == 133\n" },
2646      { -1, "SiI680: 100% native mode on irq 128\n" },
2647      { -1, "    ide0: MMIO-DMA at 0xf4800000-0xf4800007 -- "
2648            "Error, MMIO ports already in use.\n" },
2649      { -1, "    ide1: MMIO-DMA at 0xf4800008-0xf480000f -- "
2650            "Error, MMIO ports already in use.\n" },
2651      { 5, "hda: TS130220A2, ATA DISK drive\n" },
2652      { -1, "      _______________________________\n" },
2653      { -1, "     < Your System ate a SPARC! Gah! >\n" },
2654      { -1, "      -------------------------------\n" },
2655      { -1, "             \\   ^__^\n" },
2656      { -1, "              \\  (xx)\\_______\n" },
2657      { -1, "                 (__)\\       )\\/\\\n" },
2658      { -1, "                  U  ||----w |\n" },
2659      { -1, "                     ||     ||\n" },
2660      { -1, "swapper (pid 1): Breakpoint (code 0)\n" },
2661      { -1, "\n" },
2662      { -1, "     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n" },
2663      { -1, "PSW: 00000000000001001111111100001111 Not tainted\n" },
2664      { -1, "r00-03  4d6f6f21 1032f010 10208f34 103fc2e0\n" },
2665      { -1, "r04-07  103fc230 00000001 00000001 0000000f\n" },
2666      { -1, "r08-11  103454f8 000f41fa 372d3980 103ee404\n" },
2667      { -1, "r12-15  3ccbf700 10344810 103ee010 f0400004\n" },
2668      { -1, "r16-19  f00008c4 f000017c f0000174 00000000\n" },
2669      { -1, "r20-23  fed32840 fed32800 00000000 0000000a\n" },
2670      { -1, "r24-27  0000ffa0 000000ff 103fc2e0 10326010\n" },
2671      { -1, "r28-31  00000000 00061a80 4ff98340 10208f34\n" },
2672      { -1, "sr0-3   00000000 00000000 00000000 00000000\n" },
2673      { -1, "sr4-7   00000000 00000000 00000000 00000000\n" },
2674      { -1, "\n" },
2675      { -1, "IASQ: 00000000 00000000 IAOQ: 00000000 00000004\n" },
2676      { -1, " IIR: 00000000    ISR: 00000000  IOR: 00000000\n" },
2677      { -1, " CPU:        0   CR30: 4ff98000 CR31: 1037c000\n" },
2678      { -1, " ORIG_R28: 55555555\n" },
2679      { -1, " IAOQ[0]: 0x0\n" },
2680      { -1, " IAOQ[1]: 0x4\n" },
2681      { -1, " RP(r2): probe_hwif+0x218/0x44c\n" },
2682      { -1, "Kernel panic: Attempted to kill init!\n" },
2683      { 0, NULL }};
2684
2685   bst->scroll_p = True;
2686   bst->wrap_p = True;
2687   bst->left_margin = bst->right_margin = 10;
2688   bst->top_margin = bst->bottom_margin = 10;
2689
2690   release = "2.6.0-test11-pa2";
2691   sysname = "hppa";
2692   version = "#2 Mon Dec 8 06:09:27 GMT 2003";
2693 # ifdef HAVE_UNAME
2694   {
2695     struct utsname uts;
2696     char *s;
2697     if (uname (&uts) >= 0)
2698       {
2699         sysname = uts.nodename;
2700         if (!strcmp (uts.sysname, "Linux"))
2701           {
2702             release = uts.release;
2703             version = uts.version;
2704           }
2705       }
2706     s = strchr (sysname, '.');
2707     if (s) *s = 0;
2708   }
2709 # endif /* !HAVE_UNAME */
2710
2711 # if (defined (__GNUC__) && defined (__VERSION__))
2712   gccversion = __VERSION__;
2713 # else /* !(defined (__GNUC__) && defined (__VERSION__)) */
2714   gccversion = "3.3.2 (Debian)";
2715 # endif /* !(defined (__GNUC__) && defined (__VERSION__)) */
2716
2717   /* Insert current host name into banner on line 2 */
2718   {
2719     char ss[1024];
2720     snprintf (ss, 1024, linux_panic[1].string, 
2721               release, sysname, gccversion, version);
2722     linux_panic[1].string = ss;
2723   }
2724
2725   BSOD_PAUSE (bst, 100000);
2726   while (linux_panic[i].string)
2727     {
2728       if (linux_panic[i].delay != -1)
2729         linedelay = linux_panic[i].delay * 1000;
2730       BSOD_PAUSE (bst, linedelay);
2731       BSOD_TEXT (bst, LEFT, linux_panic[i].string);
2732       i++;
2733     }
2734
2735   bst->y = bst->xgwa.height - bst->font->ascent - bst->font->descent;
2736
2737   XClearWindow(dpy, window);
2738   return bst;
2739 }
2740
2741
2742 /* VMS by jwz (text sent by Roland Barmettler <roli@barmettler.net>)
2743  */
2744 static struct bsod_state *
2745 vms (Display *dpy, Window window)
2746 {
2747   struct bsod_state *bst = make_bsod_state (dpy, window, "vms", "VMS");
2748
2749   const char *sysname;
2750   int char_delay = 0;
2751   int dot_delay = 40000;
2752   int chunk_delay = 500000;
2753   char *s, *s1;
2754   int i;
2755   int arg_count;
2756
2757   __extension__
2758
2759   const char *lines[] = {
2760     "%CNXMAN,  Lost connection to system #\n"
2761     "%SHADOW-I-VOLPROC, DSA0: shadow master has changed.  "
2762     "Dump file WILL be written if system crashes.\n"
2763     "\n",
2764     "",
2765
2766     "%CNXMAN,  Quorum lost, blocking activity\n"
2767     "%CNXMAN,  Timed-out lost connection to system #\n"
2768     "%CNXMAN,  Timed-out lost connection to system #\n"
2769     "%CNXMAN,  Timed-out lost connection to system #\n"
2770     "%CNXMAN,  Proposing reconfiguration of the VMScluster\n",
2771     "",
2772
2773     "%CNXMAN,  Removed from VMScluster system #\n"
2774     "%CNXMAN,  Removed from VMScluster system #\n"
2775     "%CNXMAN,  Removed from VMScluster system #\n"
2776     "%CNXMAN,  Completing VMScluster state transition\n",
2777
2778     "\n"
2779     "**** OpenVMS (TM) Alpha Operating system V7.3-1   - BUGCHECK ****\n"
2780     "\n"
2781     "** Bugcheck code = 000005DC: CLUEXIT, Node voluntarily exiting "
2782     "VMScluster\n"
2783     "** Crash CPU: 00    Primary CPU: 00    Active CPUs: 00000001\n"
2784     "** Current Process = NULL\n"
2785     "** Current PSB ID = 00000001\n"
2786     "** Image Name =\n"
2787     "\n"
2788     "** Dumping error log buffers to HBVS unit 0\n"
2789     "**** Unable to dump error log buffers to remaining shadow set members\n"
2790     "** Error log buffers not dumped to HBVS unit 200\n"
2791     "\n"
2792     "** Dumping memory to HBVS unit 0\n"
2793     "**** Starting compressed selective memory dump at #...\n",
2794
2795     "...",
2796
2797     "\n"
2798     "**** Memory dump complete - not all processes or global pages saved\n",
2799
2800     "\n"
2801     "halted CPU 0\n",
2802     "",
2803
2804     "\n"
2805     "halt code = 5\n"
2806     "HALT instruction executed\n"
2807     "PC = ffffffff800c3884\n",
2808
2809     "\n"
2810     "CPU 0 booting\n",
2811
2812     "\n"
2813     "resetting all I/O buses\n"
2814     "\n"
2815     "\n"
2816     };
2817   char *args[8];
2818   int ids[3];
2819
2820   bst->scroll_p = True;
2821   bst->wrap_p = True;
2822   bst->left_margin = bst->right_margin = 10;
2823   bst->top_margin = bst->bottom_margin = 10;
2824
2825   sysname = "VMS001";
2826 # ifdef HAVE_UNAME
2827   {
2828     struct utsname uts;
2829     if (uname (&uts) >= 0)
2830       sysname = uts.nodename;
2831     s = strchr (sysname, '.');
2832     if (s) *s = 0;
2833   }
2834 # endif /* !HAVE_UNAME */
2835
2836   args[0] = malloc (strlen(sysname) + 7);
2837   strcpy (args[0], sysname);
2838   args[0][5] = 0;
2839
2840   /* Pick three numbers, 1-9, no overlaps. */
2841   ids[0] = 1 + (random() % 9);
2842   do { ids[1] = 1 + (random() % 9); } while (ids[1]==ids[0]);
2843   do { ids[2] = 1 + (random() % 9); } while (ids[2]==ids[0] || ids[2]==ids[1]);
2844
2845   i = strlen(args[0])-1;
2846   if (i < 6) i++;
2847   args[0][i] = '0' + ids[0];
2848   args[0][i+1] = 0;
2849
2850   for (s = args[0]; *s; s++)
2851     if (isalpha(*s)) *s = toupper (*s);
2852
2853   args[1] = strdup (args[0]);
2854   args[2] = strdup (args[0]); args[2][i] = '0' + ids[1];
2855   args[3] = strdup (args[0]); args[3][i] = '0' + ids[2];
2856
2857   args[4] = strdup (args[1]);
2858   args[5] = strdup (args[2]);
2859   args[6] = strdup (args[3]);
2860
2861   {
2862     time_t t = time ((time_t *) 0);
2863     struct tm *tm = localtime (&t);
2864     args[7] = malloc (30);
2865     strftime (args[7], 29, "%d-%b-%Y %H:%M", tm);
2866     for (s = args[7]; *s; s++)
2867       if (isalpha(*s)) *s = toupper (*s);
2868   }
2869
2870   arg_count = 0;
2871   for (i = 0; i < countof(lines); i++)
2872     {
2873       const char *fmt = lines[i];
2874       if (! strcmp (fmt, "..."))
2875         {
2876           int steps = 180 + (random() % 60);
2877           while (--steps >= 0)
2878             {
2879               BSOD_TEXT (bst, LEFT, ".");
2880               BSOD_PAUSE (bst, dot_delay);
2881             }
2882         }
2883       else
2884         {
2885           char *fmt2 = malloc (strlen (fmt) * 2 + 1);
2886           for (s = (char *) fmt, s1 = fmt2; *s; s++)
2887             {
2888               if (*s == '#')
2889                 {
2890                   strcpy (s1, args[arg_count++]);
2891                   s1 += strlen(s1);
2892                 }
2893               else
2894                 *s1++ = *s;
2895             }
2896           *s1 = 0;
2897           BSOD_CHAR_DELAY (bst, char_delay);
2898           BSOD_TEXT (bst, LEFT, fmt2);
2899           free (fmt2);
2900           BSOD_CHAR_DELAY (bst, 0);
2901           BSOD_PAUSE (bst, chunk_delay);
2902         }
2903     }
2904
2905   for (i = 0; i < countof (args); i++)
2906     free (args[i]);
2907
2908   XClearWindow(dpy, window);
2909   return bst;
2910 }
2911
2912
2913 /* HVX (formerly GCOS6) and TPS6 crash
2914    by Brian Garratt <brian-m.garratt@bull.co.uk>
2915
2916    GCOS6 is a Unix-like operating system developed by Honeywell in the
2917    1970s in collaboration with MIT and AT&T (who called their version
2918    UNIX).  Both are very much like MULTICS which Honeywell got from GE.
2919
2920    HVX ("High-performance Virtual System on Unix") is an AIX application
2921    which emulates GCOS6 hardware on RS6000-like machines.
2922  */
2923 static struct bsod_state *
2924 hvx (Display *dpy, Window window)
2925 {
2926   struct bsod_state *bst = make_bsod_state (dpy, window, "hvx", "HVX");
2927
2928   bst->scroll_p = True;
2929   bst->wrap_p = True;
2930   bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
2931
2932   BSOD_CHAR_DELAY (bst, 10000);
2933   BSOD_TEXT (bst, LEFT,
2934      "(TP) Trap no E   Effective address 00000000   Instruction D7DE\n"
2935      "(TP)  Registers :\n"
2936      "(TP)  B1 -> B7  03801B02  00000000  03880D45  038BABDB  0388AFFD"
2937      "  0389B3F8  03972317\n"
2938      "(TP)  R1 -> R7  0001  0007  F10F  090F  0020  0106  0272\n"
2939      "(TP)  P I Z M1  0388A18B  3232  0000 FF00\n"
2940      "(TP) Program counter is at offset 0028 from string YTPAD\n"
2941      "(TP) User id of task which trapped is LT 626\n"
2942      "(TP)?\n"
2943      );
2944   BSOD_PAUSE (bst, 1000000);
2945
2946   BSOD_CHAR_DELAY (bst, 100000);
2947   BSOD_TEXT (bst, LEFT, " TP CLOSE ALL");
2948
2949   BSOD_CHAR_DELAY (bst, 10000);
2950   BSOD_TEXT (bst, LEFT, "\n(TP)?\n");
2951   BSOD_PAUSE (bst, 1000000);
2952
2953   BSOD_CHAR_DELAY (bst, 100000);
2954   BSOD_TEXT (bst, LEFT, " TP ABORT -LT ALL");
2955
2956   BSOD_CHAR_DELAY (bst, 10000);
2957   BSOD_TEXT (bst, LEFT, "\n(TP)?\n");
2958   BSOD_PAUSE (bst, 1000000);
2959
2960   BSOD_CHAR_DELAY (bst, 100000);
2961   BSOD_TEXT (bst, LEFT, "  TP STOP KILL");
2962
2963   BSOD_CHAR_DELAY (bst, 10000);
2964   BSOD_TEXT (bst, LEFT,
2965      "\n"
2966      "(TP)?\n"
2967      "Core dumps initiated for selected HVX processes ...\n"
2968      "Core dumps complete.\n"
2969      "Fri Jul 19 15:53:09 2002\n"
2970      "Live registers for cp 0:\n"
2971      " P    =     7de3  IW=0000     I=32    CI=30000000   S=80006013"
2972      "   IV=aa0      Level=13\n"
2973      " R1-7 =       1f      913       13        4        8        0        0\n"
2974      " B1-7 =   64e71b      a93      50e   64e73c     6c2c     7000      b54\n"
2975      "Memory dump starting to file /var/hvx/dp01/diag/Level2 ...\n"
2976      "Memory dump complete.\n"
2977     );
2978
2979   XClearWindow(dpy, window);
2980   return bst;
2981 }
2982
2983
2984 /* HPUX panic, by Tobias Klausmann <klausman@schwarzvogel.de>
2985  */
2986 static struct bsod_state *
2987 hpux (Display *dpy, Window window)
2988 {
2989   struct bsod_state *bst = make_bsod_state (dpy, window, "hvx", "HVX");
2990   const char *sysname;
2991   char buf[2048];
2992
2993   bst->scroll_p = True;
2994   bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
2995
2996   sysname = "HPUX";
2997 # ifdef HAVE_UNAME
2998   {
2999     struct utsname uts;
3000     char *s;
3001     if (uname (&uts) >= 0)
3002       sysname = uts.nodename;
3003     s = strchr (sysname, '.');
3004     if (s) *s = 0;
3005   }
3006 # endif /* !HAVE_UNAME */
3007
3008   BSOD_TEXT (bst, LEFT,
3009              "                                                       "
3010              "                                                       "
3011              "                                                       \n");
3012   sprintf (buf, "%.100s [HP Release B.11.00] (see /etc/issue)\n", sysname);
3013   BSOD_TEXT (bst, LEFT, buf);
3014   BSOD_PAUSE (bst, 1000000);
3015   BSOD_TEXT (bst, LEFT,
3016    "Console Login:\n"
3017    "\n"
3018    "     ******* Unexpected HPMC/TOC. Processor HPA FFFFFFFF'"
3019    "FFFA0000 *******\n"
3020    "                              GENERAL REGISTERS:\n"
3021    "r00/03 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
3022    "006C76C0\n"
3023    "r04/07 00000000'00000001 00000000'0126E328 00000000'00000000 00000000'"
3024    "0122B640\n"
3025    "r08/11 00000000'00000000 00000000'0198CFC0 00000000'000476FE 00000000'"
3026    "00000001\n"
3027    "r12/15 00000000'40013EE8 00000000'08000080 00000000'4002530C 00000000'"
3028    "4002530C\n"
3029    "r16/19 00000000'7F7F2A00 00000000'00000001 00000000'00000000 00000000'"
3030    "00000000\n"
3031    "r20/23 00000000'006C8048 00000000'00000001 00000000'00000000 00000000'"
3032    "00000000\n"
3033    "r24/27 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
3034    "00744378\n"
3035    "r28/31 00000000'00000000 00000000'007DD628 00000000'0199F2B0 00000000'"
3036    "00000000\n"
3037    "                              CONTROL REGISTERS:\n"
3038    "sr0/3  00000000'0F3B4000 00000000'0C2A2000 00000000'016FF800 00000000'"
3039    "00000000\n"
3040    "sr4/7  00000000'00000000 00000000'016FF800 00000000'0DBF1400 00000000'"
3041    "00000000\n"
3042    "pcq =  00000000'00000000.00000000'00104950 00000000'00000000.00000000'"
3043    "00104A14\n"
3044    "isr =  00000000'10240006 ior = 00000000'67D9E220 iir = 08000240 rctr = "
3045    "7FF10BB6\n"
3046    "\n"
3047    "pid reg cr8/cr9    00007700'0000B3A9 00000000'0000C5D8\n"
3048    "pid reg cr12/cr13  00000000'00000000 00000000'00000000\n"
3049    "ipsw = 000000FF'080CFF1F iva = 00000000'0002C000 sar = 3A ccr = C0\n"
3050    "tr0/3  00000000'006C76C0 00000000'00000001 00000000'00000000 00000000'"
3051    "7F7CE000\n"
3052    "tr4/7  00000000'03790000 0000000C'4FB68340 00000000'C07EE13F 00000000'"
3053    "0199F2B0\n"
3054    "eiem = FFFFFFF0'FFFFFFFF eirr = 80000000'00000000 itmr = 0000000C'"
3055    "4FD8EDE1\n"
3056    "cr1/4  00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
3057    "00000000\n"
3058    "cr5/7  00000000'00000000 00000000'00000000 00000000'"
3059    "00000000\n"
3060    "                           MACHINE CHECK PARAMETERS:\n"
3061    "Check Type = 00000000 CPU STATE = 9E000001 Cache Check = 00000000\n"
3062    "TLB Check = 00000000 Bus Check = 00000000 PIM State = ? SIU "
3063    "Status = ????????\n"
3064    "Assists = 00000000 Processor = 00000000\n"
3065    "Slave Addr = 00000000'00000000 Master Addr = 00000000'00000000\n"
3066    "\n"
3067    "\n"
3068    "TOC,    pcsq.pcoq = 0'0.0'104950   , isr.ior = 0'10240006.0'67d9e220\n"
3069    "@(#)B2352B/9245XB HP-UX (B.11.00) #1: Wed Nov  5 22:38:19 PST 1997\n"
3070    "Transfer of control: (display==0xd904, flags==0x0)\n"
3071    "\n"
3072    "\n"
3073    "\n"
3074    "*** A system crash has occurred.  (See the above messages for details.)\n"
3075    "*** The system is now preparing to dump physical memory to disk, for use\n"
3076    "*** in debugging the crash.\n"
3077    "\n"
3078    "*** The dump will be a SELECTIVE dump:  40 of 256 megabytes.\n"
3079    "*** To change this dump type, press any key within 10 seconds.\n"
3080    "*** Proceeding with selective dump.\n"
3081    "\n"
3082    "*** The dump may be aborted at any time by pressing ESC.\n");
3083
3084   {
3085     int i;
3086     int steps = 11;
3087     int size = 40;
3088     for (i = 0; i <= steps; i++)
3089       {
3090         if (i > steps) i = steps;
3091         sprintf (buf, 
3092                "*** Dumping: %3d%% complete (%d of 40 MB) (device 64:0x2)\r",
3093                  i * 100 / steps,
3094                  i * size / steps);
3095         BSOD_TEXT (bst, LEFT, buf);
3096         BSOD_PAUSE (bst, 1500000);
3097       }
3098   }
3099
3100   BSOD_TEXT (bst, LEFT, "\n*** System rebooting.\n");
3101
3102   XClearWindow(dpy, window);
3103   return bst;
3104 }
3105
3106
3107 /* IBM OS/390 aka MVS aka z/OS.
3108    Text from Dan Espen <dane@mk.telcordia.com>.
3109    Apparently this isn't actually a crash, just a random session...
3110    But who can tell.
3111  */
3112 static struct bsod_state *
3113 os390 (Display *dpy, Window window)
3114 {
3115   struct bsod_state *bst = make_bsod_state (dpy, window, "os390", "OS390");
3116
3117   bst->scroll_p = True;
3118   bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
3119
3120   BSOD_LINE_DELAY (bst, 100000);
3121   BSOD_TEXT (bst, LEFT,
3122    "\n*** System rebooting.\n"
3123    "* ISPF Subtask abend *\n"
3124    "SPF      ENDED DUE TO ERROR+\n"
3125    "READY\n"
3126    "\n"
3127    "IEA995I SYMPTOM DUMP OUTPUT\n"
3128    "  USER COMPLETION CODE=0222\n"
3129    " TIME=23.00.51  SEQ=03210  CPU=0000  ASID=00AE\n"
3130    " PSW AT TIME OF ERROR  078D1000   859DAF18  ILC 2  INTC 0D\n"
3131    "   NO ACTIVE MODULE FOUND\n"
3132    "   NAME=UNKNOWN\n"
3133    "   DATA AT PSW  059DAF12 - 00181610  0A0D9180  70644710\n"
3134    "   AR/GR 0: 00000000/80000000   1: 00000000/800000DE\n"
3135    "         2: 00000000/196504DC   3: 00000000/00037A78\n"
3136    "         4: 00000000/00037B78   5: 00000000/0003351C\n"
3137    "         6: 00000000/0000F0AD   7: 00000000/00012000\n"
3138    "         8: 00000000/059DAF10   9: 00000000/0002D098\n"
3139    "         A: 00000000/059D9F10   B: 00000000/059D8F10\n"
3140    "         C: 00000000/859D7F10   D: 00000000/00032D60\n"
3141    "         E: 00000000/00033005   F: 01000002/00000041\n"
3142    " END OF SYMPTOM DUMP\n"
3143    "ISPS014 - ** Logical screen request failed - abend 0000DE **\n"
3144    "ISPS015 - ** Contact your system programmer or dialog developer.**\n"
3145    "*** ISPF Main task abend ***\n"
3146    "IEA995I SYMPTOM DUMP OUTPUT\n"
3147    "  USER COMPLETION CODE=0222\n"
3148    " TIME=23.00.52  SEQ=03211  CPU=0000  ASID=00AE\n"
3149    " PSW AT TIME OF ERROR  078D1000   8585713C  ILC 2  INTC 0D\n"
3150    "   ACTIVE LOAD MODULE           ADDRESS=05855000  OFFSET=0000213C\n"
3151    "   NAME=ISPMAIN\n"
3152    "   DATA AT PSW  05857136 - 00181610  0A0D9180  D3304770\n"
3153    "   GR 0: 80000000   1: 800000DE\n"
3154    "      2: 00015260   3: 00000038\n"
3155    "      4: 00012508   5: 00000000\n"
3156    "      6: 000173AC   7: FFFFFFF8\n"
3157    "      8: 05858000   9: 00012CA0\n"
3158    "      A: 05857000   B: 05856000\n"
3159    "      C: 85855000   D: 00017020\n"
3160    "      E: 85857104   F: 00000000\n"
3161    " END OF SYMPTOM DUMP\n"
3162    "READY\n"
3163    "***");
3164   BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999);
3165
3166   XClearWindow(dpy, window);
3167   return bst;
3168 }
3169
3170
3171 /* Compaq Tru64 Unix panic, by jwz as described by
3172    Tobias Klausmann <klausman@schwarzvogel.de>
3173  */
3174 static struct bsod_state *
3175 tru64 (Display *dpy, Window window)
3176 {
3177   struct bsod_state *bst = make_bsod_state (dpy, window, "tru64", "Tru64");
3178   const char *sysname;
3179   char buf[2048];
3180
3181   bst->scroll_p = True;
3182   bst->y = bst->xgwa.height - bst->bottom_margin - bst->font->ascent;
3183
3184   sysname = "127.0.0.1";
3185 # ifdef HAVE_UNAME
3186   {
3187     struct utsname uts;
3188     if (uname (&uts) >= 0)
3189       sysname = uts.nodename;
3190   }
3191 # endif /* !HAVE_UNAME */
3192
3193   sprintf (buf,
3194            "Compaq Tru64 UNIX V5.1B (Rev. 2650) (%.100s) console\n"
3195            "\n"
3196            "login: ",
3197            sysname);
3198   BSOD_TEXT (bst, LEFT, buf);
3199   BSOD_PAUSE (bst, 6000000);
3200
3201   BSOD_TEXT (bst, LEFT,
3202     "panic (cpu 0): trap: illegal instruction\n"
3203     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
3204     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
3205     "                                                                   \n"
3206     "DUMP: blocks available:  1571600\n"
3207     "DUMP: blocks wanted:      100802 (partial compressed dump) [OKAY]\n"
3208     "DUMP: Device     Disk Blocks Available\n"
3209     "DUMP: ------     ---------------------\n"
3210     "DUMP: 0x1300023  1182795 - 1571597 (of 1571598) [primary swap]\n"
3211     "DUMP.prom: Open: dev 0x5100041, block 2102016: SCSI 0 11 0 2 200 0 0\n"
3212     "DUMP: Writing header... [1024 bytes at dev 0x1300023, block 1571598]\n"
3213     "DUMP: Writing data");
3214
3215   {
3216     int i;
3217     int steps = 4 + (random() % 8);
3218     BSOD_CHAR_DELAY (bst, 1000000);
3219     for (i = 0; i < steps; i++)
3220       BSOD_TEXT (bst, LEFT, ".");
3221     BSOD_CHAR_DELAY (bst, 0);
3222     sprintf (buf, "[%dMB]\n", steps);
3223     BSOD_TEXT (bst, LEFT, buf);
3224   }
3225
3226   BSOD_TEXT (bst, LEFT,
3227     "DUMP: Writing header... [1024 bytes at dev 0x1300023, block 1571598]\n"
3228     "DUMP: crash dump complete.\n"
3229     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
3230     "                                                                   \n"
3231     "DUMP: second crash dump skipped: 'dump_savecnt' enforced.\n");
3232   BSOD_PAUSE (bst, 4000000);
3233
3234   BSOD_TEXT (bst, LEFT,
3235     "\n"
3236     "halted CPU 0\n"
3237     "\n"
3238     "halt code = 5\n"
3239     "HALT instruction executed\n"
3240     "PC = fffffc00005863b0\n");
3241   BSOD_PAUSE (bst, 3000000);
3242
3243   BSOD_TEXT (bst, LEFT,
3244     "\n"   
3245     "CPU 0 booting\n"
3246     "\n"
3247     "\n"
3248     "\n");
3249
3250   XClearWindow(dpy, window);
3251   return bst;
3252 }
3253
3254
3255 /* MS-DOS, by jwz
3256  */
3257 static struct bsod_state *
3258 msdos (Display *dpy, Window window)
3259 {
3260   struct bsod_state *bst = make_bsod_state (dpy, window, "msdos", "MSDOS");
3261
3262   BSOD_CHAR_DELAY (bst, 10000);
3263   BSOD_TEXT (bst, LEFT, "C:\\WINDOWS>");
3264   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 8);
3265
3266   BSOD_CHAR_DELAY (bst, 200000);
3267   BSOD_TEXT (bst, LEFT, "dir a:");
3268   BSOD_PAUSE (bst, 1000000);
3269
3270   BSOD_CHAR_DELAY (bst, 10000);
3271   BSOD_TEXT (bst, LEFT, "\nNot ready reading drive A\nAbort, Retry, Fail?");
3272
3273   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 10);
3274   BSOD_CHAR_DELAY (bst, 200000);
3275   BSOD_TEXT (bst, LEFT, "f");
3276   BSOD_PAUSE (bst, 1000000);
3277
3278   BSOD_CHAR_DELAY (bst, 10000);
3279   BSOD_TEXT (bst, LEFT,
3280              "\n\n\nNot ready reading drive A\nAbort, Retry, Fail?");
3281
3282   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 10);
3283   BSOD_CHAR_DELAY (bst, 200000);
3284   BSOD_TEXT (bst, LEFT, "f");
3285   BSOD_PAUSE (bst, 1000000);
3286
3287   BSOD_CHAR_DELAY (bst, 10000);
3288   BSOD_TEXT (bst, LEFT, "\nVolume in drive A has no label\n\n"
3289                   "Not ready reading drive A\nAbort, Retry, Fail?");
3290
3291   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 12);
3292   BSOD_CHAR_DELAY (bst, 200000);
3293   BSOD_TEXT (bst, LEFT, "a");
3294   BSOD_PAUSE (bst, 1000000);
3295
3296   BSOD_CHAR_DELAY (bst, 10000);
3297   BSOD_TEXT (bst, LEFT, "\n\nC:\\WINDOWS>");
3298
3299   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 999999);
3300
3301   XClearWindow(dpy, window);
3302   return bst;
3303 }
3304
3305
3306 /* nvidia, by jwz.
3307  *
3308  * This is what happens if an Nvidia card goes into some crazy text mode.
3309  * Most often seen on the second screen of a dual-head system when the
3310  * proper driver isn't loaded.
3311  */
3312 typedef struct { int fg; int bg; int bit; Bool blink; } nvcell;
3313
3314 static void
3315 nvspatter (nvcell *grid, int rows, int cols, int ncolors, int nbits,
3316            Bool fill_p)
3317 {
3318   int max = rows * cols;
3319   int from = fill_p ?   0 : random() % (max - 1);
3320   int len  = fill_p ? max : random() % (cols * 4);
3321   int to = from + len;
3322   int i;
3323   Bool noisy = ((random() % 4) == 0);
3324   Bool diag = (noisy || fill_p) ? 0 : ((random() % 4) == 0);
3325
3326   int fg = random() % ncolors;
3327   int bg = random() % ncolors;
3328   int blink = ((random() % 4) == 0);
3329   int bit = (random() % nbits);
3330
3331   if (to > max) to = max;
3332
3333   if (diag)
3334     {
3335       int src = random() % (rows * cols);
3336       int len2 = (cols / 2) - (random() % 5);
3337       int j = src;
3338       for (i = from; i < to; i++, j++)
3339         {
3340           if (j > src + len2 || j >= max)
3341             j = src;
3342           if (i >= max) abort();
3343           if (j >= max) abort();
3344           grid[j] = grid[i];
3345         }
3346     }
3347   else
3348     for (i = from; i < to; i++)
3349       {
3350         nvcell *cell = &grid[i];
3351         cell->fg = fg;
3352         cell->bg = bg;
3353         cell->bit = bit;
3354         cell->blink = blink;
3355
3356         if (noisy)
3357           {
3358             fg = random() % ncolors;
3359             bg = random() % ncolors;
3360             blink = ((random() % 8) == 0);
3361           }
3362       }
3363 }
3364
3365 typedef struct {
3366   struct bsod_state *bst;
3367   GC gc1;
3368   Pixmap bits[5];
3369   int rows, cols;
3370   int cellw, cellh;
3371   nvcell *grid;
3372   int ncolors;
3373   unsigned long colors[256];
3374   int tick;
3375 } nvstate;
3376
3377
3378 static void
3379 nvidia_free (struct bsod_state *bst)
3380 {
3381   nvstate *nvs = (nvstate *) bst->closure;
3382   int i;
3383   XFreeColors (bst->dpy, bst->xgwa.colormap, nvs->colors, nvs->ncolors, 0);
3384   for (i = 0; i < countof(nvs->bits); i++)
3385     XFreePixmap (bst->dpy, nvs->bits[i]);
3386   XFreeGC (bst->dpy, nvs->gc1);
3387   free (nvs->grid);
3388   free (nvs);
3389 }
3390
3391 static int
3392 nvidia_draw (struct bsod_state *bst)
3393 {
3394   nvstate *nvs = (nvstate *) bst->closure;
3395   int x, y;
3396
3397   for (y = 0; y < nvs->rows; y++)
3398     for (x = 0; x < nvs->cols; x++)
3399       {
3400         nvcell *cell = &nvs->grid[y * nvs->cols + x];
3401         unsigned long fg = nvs->colors[cell->fg];
3402         unsigned long bg = nvs->colors[cell->bg];
3403         Bool flip = cell->blink && (nvs->tick & 1);
3404         XSetForeground (bst->dpy, bst->gc, flip ? fg : bg);
3405         XSetBackground (bst->dpy, bst->gc, flip ? bg : fg);
3406         XCopyPlane (bst->dpy, nvs->bits[cell->bit], bst->window, bst->gc,
3407                     0, 0, nvs->cellw, nvs->cellh,
3408                     x * nvs->cellw, y * nvs->cellh, 1L);
3409       }
3410
3411   nvs->tick++;
3412   if ((random() % 5) == 0)    /* change the display */
3413     nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, 
3414                countof(nvs->bits), False);
3415
3416   return 250000;
3417 }
3418
3419
3420 static struct bsod_state *
3421 nvidia (Display *dpy, Window window)
3422 {
3423   struct bsod_state *bst = make_bsod_state (dpy, window, "nvidia", "nVidia");
3424   nvstate *nvs = (nvstate *) calloc (1, sizeof (*nvs));
3425
3426   XGCValues gcv;
3427   int i;
3428
3429   nvs->bst = bst;
3430   bst->closure = nvs;
3431   bst->draw_cb = nvidia_draw;
3432   bst->free_cb = nvidia_free;
3433
3434   nvs->cols = 80;
3435   nvs->rows = 25;
3436   nvs->cellw = bst->xgwa.width  / nvs->cols;
3437   nvs->cellh = bst->xgwa.height / nvs->rows;
3438   if (nvs->cellw < 8 || nvs->cellh < 18)
3439     nvs->cellw = 8, nvs->cellh = 18;
3440   nvs->cols = (bst->xgwa.width  / nvs->cellw) + 1;
3441   nvs->rows = (bst->xgwa.height / nvs->cellh) + 1;
3442
3443   nvs->grid = (nvcell *) calloc (sizeof(*nvs->grid), nvs->rows * nvs->cols);
3444
3445   /* Allocate colors
3446    */
3447   nvs->ncolors = 16;
3448   for (i = 0; i < nvs->ncolors; i++)
3449     {
3450       XColor c;
3451       c.red   = random() & 0xFFFF;
3452       c.green = random() & 0xFFFF;
3453       c.blue  = random() & 0xFFFF;
3454       c.flags = DoRed|DoGreen|DoBlue;
3455       XAllocColor (dpy, bst->xgwa.colormap, &c);
3456       nvs->colors[i] = c.pixel;
3457     }
3458
3459   /* Construct corrupted character bitmaps
3460    */
3461   for (i = 0; i < countof(nvs->bits); i++)
3462     {
3463       int j;
3464
3465       nvs->bits[i] = XCreatePixmap (dpy, window, nvs->cellw, nvs->cellh, 1);
3466       if (!nvs->gc1) nvs->gc1 = XCreateGC (dpy, nvs->bits[i], 0, &gcv);
3467
3468       XSetForeground (dpy, nvs->gc1, 0);
3469       XFillRectangle (dpy, nvs->bits[i], nvs->gc1, 0, 0, 
3470                       nvs->cellw, nvs->cellh);
3471       XSetForeground (dpy, nvs->gc1, 1);
3472
3473       if ((random() % 40) != 0)
3474         for (j = 0; j < ((nvs->cellw * nvs->cellh) / 16); j++)
3475           XFillRectangle (dpy, nvs->bits[i], nvs->gc1,
3476                           (random() % (nvs->cellw-2)) & ~1,
3477                           (random() % (nvs->cellh-2)) & ~1,
3478                           2, 2);
3479     }
3480
3481   /* Randomize the grid
3482    */
3483   nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, 
3484              countof(nvs->bits), True);
3485   for (i = 0; i < 20; i++)
3486     nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors, 
3487                countof(nvs->bits), False);
3488
3489   return bst;
3490 }
3491
3492
3493 /*
3494  * Simulate various Apple ][ crashes. The memory map encouraged many programs
3495  * to use the primary hi-res video page for various storage, and the secondary
3496  * hi-res page for active display. When it crashed into Applesoft or the
3497  * monitor, it would revert to the primary page and you'd see memory garbage on
3498  * the screen. Also, it was common for copy-protected games to use the primary
3499  * text page for important code, because that made it really hard to
3500  * reverse-engineer them. The result often looked like what this generates.
3501  *
3502  * The Apple ][ logic and video hardware is in apple2.c. The TV is emulated by
3503  * analogtv.c for maximum realism
3504  *
3505  * Trevor Blackwell <tlb@tlb.org> 
3506  */
3507
3508 static const char * const apple2_basic_errors[]={
3509   "BREAK",
3510   "NEXT WITHOUT FOR",
3511   "SYNTAX ERROR",
3512   "RETURN WITHOUT GOSUB",
3513   "ILLEGAL QUANTITY",
3514   "OVERFLOW",
3515   "OUT OF MEMORY",
3516   "BAD SUBSCRIPT ERROR",
3517   "DIVISION BY ZERO",
3518   "STRING TOO LONG",
3519   "FORMULA TOO COMPLEX",
3520   "UNDEF'D FUNCTION",
3521   "OUT OF DATA"
3522 #if 0
3523   ,
3524   "DEFAULT ARGUMENTS ARE NOT ALLOWED IN DECLARATION OF FRIEND "
3525   "TEMPLATE SPECIALIZATION"
3526 #endif
3527
3528 };
3529 static const char * const apple2_dos_errors[]={
3530   "VOLUME MISMATCH",
3531   "I/O ERROR",
3532   "DISK FULL",
3533   "NO BUFFERS AVAILABLE",
3534   "PROGRAM TOO LARGE",
3535 };
3536
3537 static void a2controller_crash(apple2_sim_t *sim, int *stepno,
3538                                double *next_actiontime)
3539 {
3540   apple2_state_t *st=sim->st;
3541   char *s;
3542   int i;
3543
3544   struct mydata {
3545     int fillptr;
3546     int fillbyte;
3547   } *mine;
3548
3549   if (!sim->controller_data)
3550     sim->controller_data = calloc(sizeof(struct mydata),1);
3551   mine=(struct mydata *) sim->controller_data;
3552   
3553   switch(*stepno) {
3554   case 0:
3555     
3556     a2_init_memory_active(sim);
3557     sim->dec->powerup = 1000.0;
3558
3559     if (random()%3==0) {
3560       st->gr_mode=0;
3561       *next_actiontime+=0.4;
3562       *stepno=100;
3563     }
3564     else if (random()%4==0) {
3565       st->gr_mode=A2_GR_LORES;
3566       if (random()%3==0) st->gr_mode |= A2_GR_FULL;
3567       *next_actiontime+=0.4;
3568       *stepno=100;
3569     }
3570     else if (random()%2==0) {
3571       st->gr_mode=A2_GR_HIRES;
3572       *stepno=300;
3573     }
3574     else {
3575       st->gr_mode=A2_GR_HIRES;
3576       *next_actiontime+=0.4;
3577       *stepno=100;
3578     }
3579     break;
3580
3581   case 100:
3582     /* An illegal instruction or a reset caused it to drop into the
3583        assembly language monitor, where you could disassemble code & view
3584        data in hex. */
3585     if (random()%3==0) {
3586       char ibytes[128];
3587       char itext[128];
3588       int addr=0xd000+random()%0x3000;
3589       sprintf(ibytes,
3590               "%02X",random()%0xff);
3591       sprintf(itext,
3592               "???");
3593       sprintf(sim->printing_buf,
3594               "\n\n"
3595               "%04X: %-15s %s\n"
3596               " A=%02X X=%02X Y=%02X S=%02X F=%02X\n"
3597               "*",
3598               addr,ibytes,itext,
3599               random()%0xff, random()%0xff,
3600               random()%0xff, random()%0xff,
3601               random()%0xff);
3602       sim->printing=sim->printing_buf;
3603       a2_goto(st,23,1);
3604       if (st->gr_mode) {
3605         *stepno=180;
3606       } else {
3607         *stepno=200;
3608       }
3609       sim->prompt='*';
3610       *next_actiontime += 2.0 + (random()%1000)*0.0002;
3611     }
3612     else {
3613       /* Lots of programs had at least their main functionality in
3614          Applesoft Basic, which had a lot of limits (memory, string
3615          length, etc) and would sometimes crash unexpectedly. */
3616       sprintf(sim->printing_buf,
3617               "\n"
3618               "\n"
3619               "\n"
3620               "?%s IN %d\n"
3621               "\001]",
3622               apple2_basic_errors[random() %
3623                                   (sizeof(apple2_basic_errors)
3624                                    /sizeof(char *))],
3625               (1000*(random()%(random()%59+1)) +
3626                100*(random()%(random()%9+1)) +
3627                5*(random()%(random()%199+1)) +
3628                1*(random()%(random()%(random()%2+1)+1))));
3629       sim->printing=sim->printing_buf;
3630       a2_goto(st,23,1);
3631       *stepno=110;
3632       sim->prompt=']';
3633       *next_actiontime += 2.0 + (random()%1000)*0.0002;
3634     }
3635     break;
3636
3637   case 110:
3638     if (random()%3==0) {
3639       /* This was how you reset the Basic interpreter. The sort of
3640          incantation you'd have on a little piece of paper taped to the
3641          side of your machine */
3642       sim->typing="CALL -1370";
3643       *stepno=120;
3644     }
3645     else if (random()%2==0) {
3646       sim->typing="CATALOG\n";
3647       *stepno=170;
3648     }
3649     else {
3650       *next_actiontime+=1.0;
3651       *stepno=999;
3652     }
3653     break;
3654
3655   case 120:
3656     *stepno=130;
3657     *next_actiontime += 0.5;
3658     break;
3659
3660   case 130:
3661     st->gr_mode=0;
3662     a2_cls(st);
3663     a2_goto(st,0,16);
3664     for (s="APPLE ]["; *s; s++) a2_printc(st,*s);
3665     a2_goto(st,23,0);
3666     a2_printc(st,']');
3667     *next_actiontime+=1.0;
3668     *stepno=999;
3669     break;
3670
3671   case 170:
3672     if (random()%50==0) {
3673       sprintf(sim->printing_buf,
3674               "\nDISK VOLUME 254\n\n"
3675               " A 002 HELLO\n"
3676               "\n"
3677               "]");
3678       sim->printing=sim->printing_buf;
3679     }
3680     else {
3681       sprintf(sim->printing_buf,"\n?%s\n]",
3682               apple2_dos_errors[random()%
3683                                 (sizeof(apple2_dos_errors) /
3684                                  sizeof(char *))]);
3685       sim->printing=sim->printing_buf;
3686     }
3687     *stepno=999;
3688     *next_actiontime+=1.0;
3689     break;
3690
3691   case 180:
3692     if (random()%2==0) {
3693       /* This was how you went back to text mode in the monitor */
3694       sim->typing="FB4BG";
3695       *stepno=190;
3696     } else {
3697       *next_actiontime+=1.0;
3698       *stepno=999;
3699     }
3700     break;
3701
3702   case 190:
3703     st->gr_mode=0;
3704     a2_invalidate(st);
3705     a2_printc(st,'\n');
3706     a2_printc(st,'*');
3707     *stepno=200;
3708     *next_actiontime+=2.0;
3709     break;
3710
3711   case 200:
3712     /* This reset things into Basic */
3713     if (random()%2==0) {
3714       sim->typing="FAA6G";
3715       *stepno=120;
3716     }
3717     else {
3718       *stepno=999;
3719       *next_actiontime+=sim->delay;
3720     }
3721     break;
3722
3723   case 300:
3724     for (i=0; i<1500; i++) {
3725       a2_poke(st, mine->fillptr, mine->fillbyte);
3726       mine->fillptr++;
3727       mine->fillbyte = (mine->fillbyte+1)&0xff;
3728     }
3729     *next_actiontime += 0.08;
3730     /* When you hit c000, it changed video settings */
3731     if (mine->fillptr>=0xc000) {
3732       a2_invalidate(st);
3733       st->gr_mode=0;
3734     }
3735     /* And it seemed to reset around here, I dunno why */
3736     if (mine->fillptr>=0xcf00) *stepno=130;
3737     break;
3738
3739   case 999:
3740     break;
3741
3742   case A2CONTROLLER_FREE:
3743     free(mine);
3744     mine = 0;
3745     break;
3746   }
3747 }
3748
3749 static int
3750 a2_draw (struct bsod_state *bst)
3751 {
3752   apple2_sim_t *sim = (apple2_sim_t *) bst->closure;
3753   if (! sim) {
3754     sim = apple2_start (bst->dpy, bst->window, 9999999, a2controller_crash);
3755     bst->closure = sim;
3756   }
3757
3758   if (! apple2_one_frame (sim)) {
3759     bst->closure = 0;
3760   }
3761
3762   return 10000;
3763 }
3764
3765 static void
3766 a2_free (struct bsod_state *bst)
3767 {
3768   apple2_sim_t *sim = (apple2_sim_t *) bst->closure;
3769   if (sim) {
3770     sim->stepno = A2CONTROLLER_DONE;
3771     a2_draw (bst);              /* finish up */
3772     if (bst->closure) abort();  /* should have been freed by now */
3773   }
3774 }
3775
3776
3777 static struct bsod_state *
3778 apple2crash (Display *dpy, Window window)
3779 {
3780   struct bsod_state *bst = make_bsod_state (dpy, window, "apple2", "Apple2");
3781   bst->draw_cb = a2_draw;
3782   bst->free_cb = a2_free;
3783   return bst;
3784 }
3785
3786
3787 /* A crash spotted on a cash machine circa 2006, by jwz.  I didn't note
3788    what model it was; probably a Tranax Mini-Bank 1000 or similar vintage.
3789  */
3790 static struct bsod_state *
3791 atm (Display *dpy, Window window)
3792 {
3793   struct bsod_state *bst = make_bsod_state (dpy, window, "atm", "ATM");
3794
3795   Pixmap pixmap = 0;
3796   int pix_w = atm_width;
3797   int pix_h = atm_height;
3798   int x, y, i = 0;
3799   float scale = 0.48;
3800
3801   XClearWindow (dpy, window);
3802
3803   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) atm_bits,
3804                                         atm_width, atm_height,
3805                                         bst->fg, bst->bg, bst->xgwa.depth);
3806
3807   while (pix_w <= bst->xgwa.width  * scale && 
3808          pix_h <= bst->xgwa.height * scale)
3809     {
3810       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
3811                               pixmap, pix_w, pix_h);
3812       pix_w *= 2;
3813       pix_h *= 2;
3814       i++;
3815     }
3816
3817   x = (bst->xgwa.width  - pix_w) / 2;
3818   y = (bst->xgwa.height - pix_h) / 2;
3819   if (y < 0) y = 0;
3820
3821   if (i > 0)
3822     {
3823       int j;
3824       XSetForeground (dpy, bst->gc,
3825                       get_pixel_resource (dpy, bst->xgwa.colormap,
3826                                           "atm.background",
3827                                           "ATM.Background"));
3828       for (j = -1; j < pix_w; j += i+1)
3829         XDrawLine (bst->dpy, pixmap, bst->gc, j, 0, j, pix_h);
3830       for (j = -1; j < pix_h; j += i+1)
3831         XDrawLine (bst->dpy, pixmap, bst->gc, 0, j, pix_w, j);
3832     }
3833
3834   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
3835
3836   XFreePixmap (dpy, pixmap);
3837
3838   return bst;
3839 }
3840
3841
3842 /*****************************************************************************
3843  *****************************************************************************/
3844
3845
3846 static const struct {
3847   const char *name;
3848   struct bsod_state * (*fn) (Display *, Window);
3849 } all_modes[] = {
3850   { "Windows",          windows_31 },
3851   { "NT",               windows_nt },
3852   { "Win2K",            windows_other },
3853   { "Amiga",            amiga },
3854   { "Mac",              mac },
3855   { "MacsBug",          macsbug },
3856   { "Mac1",             mac1 },
3857   { "MacX",             macx },
3858   { "SCO",              sco },
3859   { "HVX",              hvx },
3860   { "HPPALinux",        hppa_linux },
3861   { "SparcLinux",       sparc_linux },
3862   { "BSD",              bsd },
3863   { "Atari",            atari },
3864 #ifndef HAVE_COCOA
3865   { "BlitDamage",       blitdamage },
3866 #endif
3867   { "Solaris",          sparc_solaris },
3868   { "Linux",            linux_fsck },
3869   { "HPUX",             hpux },
3870   { "OS390",            os390 },
3871   { "Tru64",            tru64 },
3872   { "VMS",              vms },
3873   { "OS2",              os2 },
3874   { "MSDOS",            msdos },
3875   { "Nvidia",           nvidia },
3876   { "Apple2",           apple2crash },
3877   { "ATM",              atm },
3878   { "GLaDOS",           glados },
3879 };
3880
3881
3882 struct driver_state {
3883   const char *name;
3884   int only, which;
3885   int delay;
3886   time_t start;
3887   Bool debug_p, cycle_p;
3888   struct bsod_state *bst;
3889 };
3890
3891
3892 static void
3893 hack_title (struct driver_state *dst)
3894 {
3895 # ifndef HAVE_COCOA
3896   char *oname = 0;
3897   XFetchName (dst->bst->dpy, dst->bst->window, &oname);
3898   if (oname && !strncmp (oname, "BSOD: ", 6)) {
3899     char *tail = oname + 4;
3900     char *s = strchr (tail+1, ':');
3901     char *nname;
3902     if (s) tail = s;
3903     nname = malloc (strlen (tail) + strlen (dst->name) + 20);
3904     sprintf (nname, "BSOD: %s%s", dst->name, tail);
3905     XStoreName (dst->bst->dpy, dst->bst->window, nname);
3906     free (nname);
3907   }
3908 # endif /* !HAVE_COCOA */
3909 }
3910
3911 static void *
3912 bsod_init (Display *dpy, Window window)
3913 {
3914   struct driver_state *dst = (struct driver_state *) calloc (1, sizeof(*dst));
3915   char *s;
3916
3917   dst->delay = get_integer_resource (dpy, "delay", "Integer");
3918   if (dst->delay < 3) dst->delay = 3;
3919
3920   dst->debug_p = get_boolean_resource (dpy, "debug", "Boolean");
3921
3922   dst->only = -1;
3923   s = get_string_resource(dpy, "doOnly", "DoOnly");
3924   if (s && !strcasecmp (s, "cycle"))
3925     {
3926       dst->which = -1;
3927       dst->cycle_p = True;
3928     }
3929   else if (s && *s)
3930     {
3931       int count = countof(all_modes);
3932       for (dst->only = 0; dst->only < count; dst->only++)
3933         if (!strcasecmp (s, all_modes[dst->only].name))
3934           break;
3935       if (dst->only >= count)
3936         {
3937           fprintf (stderr, "%s: unknown -only mode: \"%s\"\n", progname, s);
3938           dst->only = -1;
3939         }
3940     }
3941   if (s) free (s);
3942
3943   dst->name = "none";
3944   dst->which = -1;
3945   return dst;
3946 }
3947
3948
3949 static unsigned long
3950 bsod_draw (Display *dpy, Window window, void *closure)
3951 {
3952   struct driver_state *dst = (struct driver_state *) closure;
3953   time_t now;
3954   int time_left;
3955
3956  AGAIN:
3957   now = time ((time_t *) 0);
3958   time_left = dst->start + dst->delay - now;
3959
3960   if (dst->bst && dst->bst->img_loader)   /* still loading */
3961     {
3962       dst->bst->img_loader = 
3963         load_image_async_simple (dst->bst->img_loader, 0, 0, 0, 0, 0);
3964       return 100000;
3965     }
3966
3967   if (! dst->bst && time_left > 0)      /* run completed; wait out the delay */
3968     {
3969       if (dst->debug_p)
3970         fprintf (stderr, "%s: %s: %d left\n", progname, dst->name, time_left);
3971       return 500000;
3972     }
3973
3974   else if (dst->bst)                    /* sub-mode currently running */
3975     {
3976       int this_delay = -1;
3977
3978       if (time_left > 0)
3979         this_delay = bsod_pop (dst->bst);
3980
3981       /* XSync (dpy, False);  slows down char drawing too much on HAVE_COCOA */
3982
3983       if (this_delay == 0)
3984         goto AGAIN;                     /* no delay, not expired: stay here */
3985       else if (this_delay >= 0)
3986         return this_delay;              /* return; time to sleep */
3987       else
3988         {                               /* sub-mode run completed or expired */
3989           if (dst->debug_p)
3990             fprintf (stderr, "%s: %s: done\n", progname, dst->name);
3991           free_bsod_state (dst->bst);
3992           dst->bst = 0;
3993           return 0;
3994         }
3995     }
3996   else                                  /* launch a new sub-mode */
3997     {
3998       if (dst->cycle_p)
3999         dst->which = (dst->which + 1) % countof(all_modes);
4000       else if (dst->only >= 0)
4001         dst->which = dst->only;
4002       else
4003         {
4004           int count = countof(all_modes);
4005           int i;
4006
4007           for (i = 0; i < 200; i++)
4008             {
4009               char name[100], class[100];
4010               int new_mode = (random() & 0xFF) % count;
4011
4012               if (i < 100 && new_mode == dst->which)
4013                 continue;
4014
4015               sprintf (name,  "do%s", all_modes[new_mode].name);
4016               sprintf (class, "Do%s", all_modes[new_mode].name);
4017
4018               if (get_boolean_resource (dpy, name, class))
4019                 {
4020                   dst->which = new_mode;
4021                   break;
4022                 }
4023             }
4024
4025           if (i >= 200)
4026             {
4027               fprintf (stderr, "%s: no display modes enabled?\n", progname);
4028               /* exit (-1); */
4029               dst->which = dst->only = 0;
4030             }
4031         }
4032           
4033       if (dst->debug_p)
4034         fprintf (stderr, "%s: %s: launch\n", progname, 
4035                  all_modes[dst->which].name);
4036
4037       /* Run the mode setup routine...
4038        */
4039       if (dst->bst) abort();
4040       dst->name  = all_modes[dst->which].name;
4041       dst->bst   = all_modes[dst->which].fn (dpy, window);
4042       dst->start = (dst->bst ? time ((time_t *) 0) : 0);
4043
4044       /* Reset the structure run state to the beginning,
4045          and do some sanitization of the cursor position
4046          before the first run.
4047        */
4048       if (dst->bst)
4049         {
4050           if (dst->debug_p)
4051             fprintf (stderr, "%s: %s: queue size: %d (%d)\n", progname, 
4052                      dst->name, dst->bst->pos, dst->bst->queue_size);
4053
4054           hack_title (dst);
4055           dst->bst->pos = 0;
4056           dst->bst->x = dst->bst->current_left = dst->bst->left_margin;
4057
4058           if (dst->bst->y < dst->bst->top_margin + dst->bst->font->ascent)
4059             dst->bst->y = dst->bst->top_margin + dst->bst->font->ascent;
4060         }
4061     }
4062
4063   return 0;
4064 }
4065
4066
4067 static void
4068 bsod_reshape (Display *dpy, Window window, void *closure, 
4069               unsigned int w, unsigned int h)
4070 {
4071   struct driver_state *dst = (struct driver_state *) closure;
4072
4073   if (dst->bst &&
4074       w == dst->bst->xgwa.width &&
4075       h == dst->bst->xgwa.height)
4076     return;
4077
4078   if (dst->debug_p)
4079     fprintf (stderr, "%s: %s: reshape reset\n", progname, dst->name);
4080
4081   /* just pick a new mode and restart when the window is resized. */
4082   if (dst->bst)
4083     free_bsod_state (dst->bst);
4084   dst->bst = 0;
4085   dst->start = 0;
4086   dst->name = "none";
4087   XClearWindow (dpy, window);
4088 }
4089
4090
4091 static Bool
4092 bsod_event (Display *dpy, Window window, void *closure, XEvent *event)
4093 {
4094   struct driver_state *dst = (struct driver_state *) closure;
4095   Bool reset_p = False;
4096
4097   /* pick a new mode and restart when mouse clicked, or certain keys typed. */
4098
4099   if (event->type == ButtonPress)
4100     return True;
4101   else if (event->type == ButtonRelease)
4102     reset_p = True;
4103   else if (event->type == KeyPress)
4104     {
4105       KeySym keysym;
4106       char c = 0;
4107       XLookupString (&event->xkey, &c, 1, &keysym, 0);
4108       if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
4109         reset_p = True;
4110     }
4111
4112   if (reset_p)
4113     {
4114       if (dst->debug_p)
4115         fprintf (stderr, "%s: %s: manual reset\n", progname, dst->name);
4116       if (dst->bst)
4117         free_bsod_state (dst->bst);
4118       dst->bst = 0;
4119       dst->start = 0;
4120       dst->name = "none";
4121       XClearWindow (dpy, window);
4122       return True;
4123     }
4124   else
4125     return False;
4126 }
4127
4128
4129 static void
4130 bsod_free (Display *dpy, Window window, void *closure)
4131 {
4132   struct driver_state *dst = (struct driver_state *) closure;
4133   if (dst->bst)
4134     free_bsod_state (dst->bst);
4135   free (dst);
4136 }
4137
4138
4139 static const char *bsod_defaults [] = {
4140   "*delay:                 30",
4141   "*debug:                 False",
4142
4143   "*doOnly:                ",
4144   "*doWindows:             True",
4145   "*doNT:                  True",
4146   "*doWin2K:               True",
4147   "*doAmiga:               True",
4148   "*doMac:                 True",
4149   "*doMacsBug:             True",
4150   "*doMac1:                True",
4151   "*doMacX:                True",
4152   "*doSCO:                 True",
4153   "*doAtari:               False",      /* boring */
4154   "*doBSD:                 False",      /* boring */
4155   "*doLinux:               True",
4156   "*doSparcLinux:          False",      /* boring */
4157   "*doHPPALinux:           True",
4158   "*doBlitDamage:          True",
4159   "*doSolaris:             True",
4160   "*doHPUX:                True",
4161   "*doTru64:               True",
4162   "*doApple2:              True",
4163   "*doOS390:               True",
4164   "*doVMS:                 True",
4165   "*doHVX:                 True",
4166   "*doMSDOS:               True",
4167   "*doOS2:                 True",
4168   "*doNvidia:              True",
4169   "*doATM:                 True",
4170   "*doGLaDOS:              True",
4171
4172   "*font:                  9x15bold",
4173   "*font2:                 -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
4174   "*bigFont:               -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
4175   "*bigFont2:              -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
4176
4177   ".foreground:            White",
4178   ".background:            Black",
4179
4180   ".windows.foreground:    White",
4181   ".windows.background:    #0000AA",    /* EGA color 0x01. */
4182
4183   ".windowslh.foreground:  White",
4184   ".windowslh.background:  #AA0000",    /* EGA color 0x04. */
4185   ".windowslh.background2: #AAAAAA",    /* EGA color 0x07. */
4186
4187   ".glaDOS.foreground:     White",
4188   ".glaDOS.background:     #0000AA",    /* EGA color 0x01. */
4189
4190   ".amiga.foreground:      #FF0000",
4191   ".amiga.background:      Black",
4192   ".amiga.background2:     White",
4193
4194   ".mac.foreground:        #BBFFFF",
4195   ".mac.background:        Black",
4196
4197   ".atari.foreground:      Black",
4198   ".atari.background:      White",
4199
4200   ".macsbug.font:          -*-courier-medium-r-*-*-*-80-*-*-m-*-*-*",
4201   ".macsbug.bigFont:       -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4202   ".macsbug.foreground:    Black",
4203   ".macsbug.background:    White",
4204   ".macsbug.borderColor:   #AAAAAA",
4205
4206   ".mac1.foreground:       Black",
4207   ".mac1.background:       White",
4208
4209   ".macx.foreground:       White",
4210   ".macx.textForeground:   White",
4211   ".macx.textBackground:   Black",
4212   ".macx.background:       #888888",
4213
4214   ".macdisk.font:          -*-courier-bold-r-*-*-*-80-*-*-m-*-*-*",
4215   ".macdisk.bigFont:       -*-courier-bold-r-*-*-*-100-*-*-m-*-*-*",
4216
4217   ".sco.font:              -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4218   ".sco.foreground:        White",
4219   ".sco.background:        Black",
4220
4221   ".hvx.font:              -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4222   ".hvx.foreground:        White",
4223   ".hvx.background:        Black",
4224
4225   ".linux.foreground:      White",
4226   ".linux.background:      Black",
4227
4228   ".hppalinux.bigFont:     -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4229   ".hppalinux.foreground:  White",
4230   ".hppalinux.background:  Black",
4231
4232   ".sparclinux.bigFont:    -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4233   ".sparclinux.foreground: White",
4234   ".sparclinux.background: Black",
4235
4236   ".bsd.font:              vga",
4237   ".bsd.bigFont:           -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*",
4238   ".bsd.bigFont2:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4239   ".bsd.foreground:        #c0c0c0",
4240   ".bsd.background:        Black",
4241
4242   ".solaris.font:          -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
4243   ".solaris.foreground:    Black",
4244   ".solaris.background:    White",
4245
4246   ".hpux.bigFont:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4247   ".hpux.foreground:       White",
4248   ".hpux.background:       Black",
4249
4250   ".os390.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4251   ".os390.background:      Black",
4252   ".os390.foreground:      Red",
4253
4254   ".tru64.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4255   ".tru64.foreground:      White",
4256   ".tru64.background:      #0000AA",    /* EGA color 0x01. */
4257
4258   ".vms.bigFont:           -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4259   ".vms.foreground:        White",
4260   ".vms.background:        Black",
4261
4262   ".msdos.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
4263   ".msdos.foreground:      White",
4264   ".msdos.background:      Black",
4265
4266   ".os2.foreground:        White",
4267   ".os2.background:        Black",
4268
4269   ".atm.foreground:        Black",
4270   ".atm.background:        #FF6600",
4271
4272   "*dontClearRoot:         True",
4273
4274   ANALOGTV_DEFAULTS
4275
4276 #ifdef HAVE_XSHM_EXTENSION
4277   "*useSHM:                True",
4278 #endif
4279
4280 # ifdef USE_IPHONE
4281   "*font:                  Courier-Bold 9",
4282   ".amiga.font:            Courier-Bold 12",
4283   ".macsbug.font:          Courier-Bold 5",
4284   ".sco.font:              Courier-Bold 9",
4285   ".hvx.font:              Courier-Bold 9",
4286   ".bsd.font:              Courier-Bold 9",
4287   ".solaris.font:          Courier-Bold 6",
4288   ".macdisk.font:          Courier-Bold 6",
4289 # endif
4290
4291   0
4292 };
4293
4294 static const XrmOptionDescRec bsod_options [] = {
4295   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
4296   { "-only",            ".doOnly",              XrmoptionSepArg, 0 },
4297   { "-debug",           ".debug",               XrmoptionNoArg,  "True"  },
4298   { "-windows",         ".doWindows",           XrmoptionNoArg,  "True"  },
4299   { "-no-windows",      ".doWindows",           XrmoptionNoArg,  "False" },
4300   { "-nt",              ".doNT",                XrmoptionNoArg,  "True"  },
4301   { "-no-nt",           ".doNT",                XrmoptionNoArg,  "False" },
4302   { "-2k",              ".doWin2K",             XrmoptionNoArg,  "True"  },
4303   { "-no-2k",           ".doWin2K",             XrmoptionNoArg,  "False" },
4304   { "-amiga",           ".doAmiga",             XrmoptionNoArg,  "True"  },
4305   { "-no-amiga",        ".doAmiga",             XrmoptionNoArg,  "False" },
4306   { "-mac",             ".doMac",               XrmoptionNoArg,  "True"  },
4307   { "-no-mac",          ".doMac",               XrmoptionNoArg,  "False" },
4308   { "-mac1",            ".doMac1",              XrmoptionNoArg,  "True"  },
4309   { "-no-mac1",         ".doMac1",              XrmoptionNoArg,  "False" },
4310   { "-macx",            ".doMacX",              XrmoptionNoArg,  "True"  },
4311   { "-no-macx",         ".doMacX",              XrmoptionNoArg,  "False" },
4312   { "-atari",           ".doAtari",             XrmoptionNoArg,  "True"  },
4313   { "-no-atari",        ".doAtari",             XrmoptionNoArg,  "False" },
4314   { "-macsbug",         ".doMacsBug",           XrmoptionNoArg,  "True"  },
4315   { "-no-macsbug",      ".doMacsBug",           XrmoptionNoArg,  "False" },
4316   { "-apple2",          ".doApple2",            XrmoptionNoArg,  "True"  },
4317   { "-no-apple2",       ".doApple2",            XrmoptionNoArg,  "False" },
4318   { "-sco",             ".doSCO",               XrmoptionNoArg,  "True"  },
4319   { "-no-sco",          ".doSCO",               XrmoptionNoArg,  "False" },
4320   { "-hvx",             ".doHVX",               XrmoptionNoArg,  "True"  },
4321   { "-no-hvx",          ".doHVX",               XrmoptionNoArg,  "False" },
4322   { "-bsd",             ".doBSD",               XrmoptionNoArg,  "True"  },
4323   { "-no-bsd",          ".doBSD",               XrmoptionNoArg,  "False" },
4324   { "-linux",           ".doLinux",             XrmoptionNoArg,  "True"  },
4325   { "-no-linux",        ".doLinux",             XrmoptionNoArg,  "False" },
4326   { "-hppalinux",       ".doHPPALinux",         XrmoptionNoArg,  "True"  },
4327   { "-no-hppalinux",    ".doHPPALinux",         XrmoptionNoArg,  "False" },
4328   { "-sparclinux",      ".doSparcLinux",        XrmoptionNoArg,  "True"  },
4329   { "-no-sparclinux",   ".doSparcLinux",        XrmoptionNoArg,  "False" },
4330   { "-blitdamage",      ".doBlitDamage",        XrmoptionNoArg,  "True"  },
4331   { "-no-blitdamage",   ".doBlitDamage",        XrmoptionNoArg,  "False" },
4332   { "-nvidia",          ".doNvidia",            XrmoptionNoArg,  "True"  },
4333   { "-no-nvidia",       ".doNvidia",            XrmoptionNoArg,  "False" },
4334   { "-solaris",         ".doSolaris",           XrmoptionNoArg,  "True"  },
4335   { "-no-solaris",      ".doSolaris",           XrmoptionNoArg,  "False" },
4336   { "-hpux",            ".doHPUX",              XrmoptionNoArg,  "True"  },
4337   { "-no-hpux",         ".doHPUX",              XrmoptionNoArg,  "False" },
4338   { "-os390",           ".doOS390",             XrmoptionNoArg,  "True"  },
4339   { "-no-os390",        ".doOS390",             XrmoptionNoArg,  "False" },
4340   { "-tru64",           ".doHPUX",              XrmoptionNoArg,  "True"  },
4341   { "-no-tru64",        ".doTru64",             XrmoptionNoArg,  "False" },
4342   { "-vms",             ".doVMS",               XrmoptionNoArg,  "True"  },
4343   { "-no-vms",          ".doVMS",               XrmoptionNoArg,  "False" },
4344   { "-msdos",           ".doMSDOS",             XrmoptionNoArg,  "True"  },
4345   { "-no-msdos",        ".doMSDOS",             XrmoptionNoArg,  "False" },
4346   { "-os2",             ".doOS2",               XrmoptionNoArg,  "True"  },
4347   { "-no-os2",          ".doOS2",               XrmoptionNoArg,  "False" },
4348   { "-atm",             ".doATM",               XrmoptionNoArg,  "True"  },
4349   { "-no-atm",          ".doATM",               XrmoptionNoArg,  "False" },
4350   { "-glados",          ".doGLaDOS",            XrmoptionNoArg,  "True"  },
4351   { "-no-glados",       ".doGLaDOS",            XrmoptionNoArg,  "False" },
4352   ANALOGTV_OPTIONS
4353   { 0, 0, 0, 0 }
4354 };
4355
4356
4357 XSCREENSAVER_MODULE ("BSOD", bsod)