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