From http://www.jwz.org/xscreensaver/xscreensaver-5.38.tar.gz
[xscreensaver] / hacks / bsod.c
1 /* xscreensaver, Copyright (c) 1998-2017 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 #include <time.h>
44
45 #ifdef HAVE_XSHM_EXTENSION
46 #include "xshm.h"
47 #endif
48
49 #ifdef HAVE_UNAME
50 # include <sys/utsname.h>
51 #endif /* HAVE_UNAME */
52
53 #if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM) || defined(HAVE_JWXYZ)
54 # define DO_XPM
55 #endif
56
57 #ifdef DO_XPM
58 # include "images/amiga.xpm"
59 # include "images/hmac.xpm"
60 # include "images/osx_10_2.xpm"
61 # include "images/osx_10_3.xpm"
62 # include "images/android.xpm"
63 # include "images/ransomware.xpm"
64 #endif
65 #include "images/atari.xbm"
66 #include "images/mac.xbm"
67 #include "images/macbomb.xbm"
68 #include "images/apple.xbm"
69 #include "images/atm.xbm"
70
71 #undef countof
72 #define countof(x) (sizeof((x))/sizeof((*x)))
73
74 # undef MIN
75 # undef MAX
76 # define MIN(A,B) ((A)<(B)?(A):(B))
77 # define MAX(A,B) ((A)>(B)?(A):(B))
78
79 #undef EOF
80 typedef enum { EOF=0,
81                LEFT, CENTER, RIGHT,
82                LEFT_FULL, CENTER_FULL, RIGHT_FULL,
83                COLOR, INVERT, MOVETO, MARGINS,
84                CURSOR_BLOCK, CURSOR_LINE, RECT, LINE, COPY, PIXMAP, IMG, FONT,
85                PAUSE, CHAR_DELAY, LINE_DELAY,
86                LOOP, RESET, VERT_MARGINS, CROP
87 } bsod_event_type;
88
89 struct bsod_event {
90   bsod_event_type type;
91   void *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
92 };
93
94 struct bsod_state {
95   Display *dpy;
96   Window window;
97   XWindowAttributes xgwa;
98   XFontStruct *font, *fontA, *fontB, *fontC;
99   unsigned long fg, bg;
100   GC gc;
101   int left_margin, right_margin;        /* for text wrapping */
102   int top_margin, bottom_margin;        /* for text scrolling and cropping */
103   int xoff, yoff;
104   Bool wrap_p;
105   Bool scroll_p;
106   Bool crop_p;                  /* If True, chops off extra text vertically */
107
108   Pixmap pixmap;                /* Source image used by BSOD_PIXMAP */
109
110   int x, y;                     /* current text-drawing position */
111   int current_left;             /* don't use this */
112
113   int pos;                      /* position in queue */
114   int queue_size;
115   struct bsod_event *queue;
116
117   unsigned long char_delay;     /* delay between printing characters */
118   unsigned long line_delay;     /* delay between printing lines */
119
120   Bool macx_eol_kludge;
121
122   void *closure;
123   int  (*draw_cb) (struct bsod_state *);
124   void (*free_cb) (struct bsod_state *);
125
126   async_load_state *img_loader;
127 };
128
129
130 # if !defined(__GNUC__) && !defined(__extension__)
131   /* don't warn about "string length is greater than the length ISO C89
132      compilers are required to support" in these string constants... */
133 #  define  __extension__ /**/
134 # endif
135
136
137 /* Draw text at the current position; align is LEFT, CENTER, RIGHT, or *_FULL
138    (meaning to clear the whole line margin to margin).
139  */
140 #define BSOD_TEXT(bst,align,string) do { \
141   ensure_queue (bst); \
142   (bst)->queue[(bst)->pos].type = (align); \
143   (bst)->queue[(bst)->pos].arg1 = (void *) strdup (__extension__ (string)); \
144   (bst)->queue[(bst)->pos].arg2 = (bst)->queue[(bst)->pos].arg1; \
145   (bst)->queue[(bst)->pos].arg3 = (void *) 0; \
146   (bst)->pos++; \
147   } while (0)
148
149 /* Flip the foreground and background colors
150  */
151 #define BSOD_INVERT(bst) do { \
152   ensure_queue (bst); \
153   (bst)->queue[(bst)->pos].type = INVERT; \
154   (bst)->pos++; \
155   } while (0)
156
157 /* Set the foreground and background colors to the given pixels
158  */
159 #define BSOD_COLOR(bst,fg,bg) do { \
160   ensure_queue (bst); \
161   (bst)->queue[(bst)->pos].type = COLOR; \
162   (bst)->queue[(bst)->pos].arg1 = (void *) fg; \
163   (bst)->queue[(bst)->pos].arg2 = (void *) bg; \
164   (bst)->pos++; \
165   } while (0)
166
167 /* Set the position of the next text.
168    Note that this is the baseline: lower left corner of next char printed.
169  */
170 #define BSOD_MOVETO(bst,x,y) do { \
171   ensure_queue (bst); \
172   (bst)->queue[(bst)->pos].type = MOVETO; \
173   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (x)); \
174   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (y)); \
175   (bst)->pos++; \
176   } while (0)
177
178 /* Delay for at least the given number of microseconds.
179  */
180 #define BSOD_PAUSE(bst,usec) do { \
181   ensure_queue (bst); \
182   (bst)->queue[(bst)->pos].type = PAUSE; \
183   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (usec)); \
184   (bst)->pos++; \
185   } while (0)
186
187 /* Set the delay after each character is printed.
188  */
189 #define BSOD_CHAR_DELAY(bst,usec) do { \
190   ensure_queue (bst); \
191   (bst)->queue[(bst)->pos].type = CHAR_DELAY; \
192   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (usec)); \
193   (bst)->pos++; \
194   } while (0)
195
196 /* Set the delay after each newline.
197  */
198 #define BSOD_LINE_DELAY(bst,usec) do { \
199   ensure_queue (bst); \
200   (bst)->queue[(bst)->pos].type = LINE_DELAY; \
201   (bst)->queue[(bst)->pos].arg1 = (void *) (usec); \
202   (bst)->pos++; \
203   } while (0)
204
205 /* Set the prevailing left/right margins (used when strings have
206    embedded newlines, and when centering or right-justifying text.)
207  */
208 #define BSOD_MARGINS(bst,left,right) do { \
209   ensure_queue (bst); \
210   (bst)->queue[(bst)->pos].type = MARGINS; \
211   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (left)); \
212   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (right)); \
213   (bst)->pos++; \
214   } while (0)
215
216 /* Set the prevailing top/bottom margins (used when scrolling and cropping text)
217  */
218 #define BSOD_VERT_MARGINS(bst,top,bottom) do { \
219   ensure_queue (bst); \
220   (bst)->queue[(bst)->pos].type = VERT_MARGINS; \
221   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (top)); \
222   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (bottom)); \
223   (bst)->pos++; \
224   } while (0)
225
226 /* Draw a blinking cursor; type is CURSOR_BLOCK or CURSOR_LINE.
227    usec is how long 1/2 of a cycle is.  count is how many times to blink.
228    (You can pass a gigantic number if this is the last thing in your mode.)
229  */
230 #define BSOD_CURSOR(bst,ctype,usec,count) do { \
231   ensure_queue (bst); \
232   (bst)->queue[(bst)->pos].type = (ctype); \
233   (bst)->queue[(bst)->pos].arg1 = (void *) (usec); \
234   (bst)->queue[(bst)->pos].arg2 = (void *) (count); \
235   (bst)->pos++; \
236   } while (0)
237
238 /* Draw or fill a rectangle.  You can set line-width in the GC.
239  */
240 #define BSOD_RECT(bst,fill,x,y,w,h) do { \
241   ensure_queue (bst); \
242   (bst)->queue[(bst)->pos].type = RECT; \
243   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (fill)); \
244   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (x)); \
245   (bst)->queue[(bst)->pos].arg3 = (void *) ((long) (y)); \
246   (bst)->queue[(bst)->pos].arg4 = (void *) ((long) (w)); \
247   (bst)->queue[(bst)->pos].arg5 = (void *) ((long) (h)); \
248   (bst)->pos++; \
249   } while (0)
250
251 /* Draw a line.
252  */
253 #define BSOD_LINE(bst,x,y,x2,y2,thick) do { \
254   ensure_queue (bst); \
255   (bst)->queue[(bst)->pos].type = LINE; \
256   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (x)); \
257   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (y)); \
258   (bst)->queue[(bst)->pos].arg3 = (void *) ((long) (x2)); \
259   (bst)->queue[(bst)->pos].arg4 = (void *) ((long) (y2)); \
260   (bst)->queue[(bst)->pos].arg5 = (void *) ((long) (thick)); \
261   (bst)->pos++; \
262   } while (0)
263
264 /* Copy a rect from the window, to the window.
265  */
266 #define BSOD_COPY(bst,srcx,srcy,w,h,tox,toy) do { \
267   ensure_queue (bst); \
268   (bst)->queue[(bst)->pos].type = COPY; \
269   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (srcx)); \
270   (bst)->queue[(bst)->pos].arg2 = (void *) ((long) (srcy)); \
271   (bst)->queue[(bst)->pos].arg3 = (void *) ((long) (w)); \
272   (bst)->queue[(bst)->pos].arg4 = (void *) ((long) (h)); \
273   (bst)->queue[(bst)->pos].arg5 = (void *) ((long) (tox)); \
274   (bst)->queue[(bst)->pos].arg6 = (void *) ((long) (toy)); \
275   (bst)->pos++; \
276   } while (0)
277
278 /* Copy a rect from bst->pixmap to the window.
279  */
280 #define BSOD_PIXMAP(bst,srcx,srcy,w,h,tox,toy) do { \
281   BSOD_COPY(bst,srcx,srcy,w,h,tox,toy); \
282   (bst)->queue[(bst)->pos-1].type = PIXMAP; \
283   } while (0)
284
285 /* Load a random image (or the desktop) onto the window.
286  */
287 #define BSOD_IMG(bst) do { \
288   ensure_queue (bst); \
289   (bst)->queue[(bst)->pos].type = IMG; \
290   (bst)->pos++; \
291   } while (0)
292
293 /* Switch between fonts A, B and C.
294  */
295 #define BSOD_FONT(bst,n) do { \
296   ensure_queue (bst); \
297   (bst)->queue[(bst)->pos].type = FONT; \
298   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (n)); \
299   (bst)->pos++; \
300   } while (0)
301
302 /* Jump around in the state table.  You can use this as the last thing
303    in your state table to repeat the last N elements forever.
304  */
305 #define BSOD_LOOP(bst,off) do { \
306   ensure_queue (bst); \
307   (bst)->queue[(bst)->pos].type = LOOP; \
308   (bst)->queue[(bst)->pos].arg1 = (void *) (off); \
309   (bst)->pos++; \
310   } while (0)
311
312 /* Restart the whole thing from the beginning.
313  */
314 #define BSOD_RESET(bst) do { \
315   ensure_queue (bst); \
316   (bst)->queue[(bst)->pos].type = RESET; \
317   (bst)->pos++; \
318   } while (0)
319
320 /* Sets the crop state, if True, will not write text below the bottom_margin
321  */
322 #define BSOD_CROP(bst, state) do { \
323   ensure_queue (bst); \
324   (bst)->queue[(bst)->pos].type = CROP; \
325   (bst)->queue[(bst)->pos].arg1 = (void *) ((long) (state)); \
326   (bst)->pos++; \
327   } while (0)
328
329
330
331 static void
332 ensure_queue (struct bsod_state *bst)
333 {
334   int n;
335   if (bst->pos + 1 < bst->queue_size)
336     return;
337
338   n = bst->queue_size + 10;
339   if (n < 100) n *= 2;
340   n *= 1.2;
341
342   bst->queue = (struct bsod_event *)
343     realloc (bst->queue, n * sizeof(*bst->queue));
344   if (!bst->queue) abort();
345   memset (bst->queue + bst->queue_size, 0,
346           (n - bst->queue_size) * sizeof(*bst->queue));
347   bst->queue_size = n;
348 }
349
350
351 static void
352 position_for_text (struct bsod_state *bst, const char *line)
353 {
354   int max_width = 0;
355
356   const char *start = line;
357
358   if (bst->queue[bst->pos].type != LEFT &&
359       bst->queue[bst->pos].type != LEFT_FULL)
360     while (*start)
361       {
362         int dir, ascent, descent;
363         XCharStruct ov;
364         const char *end = start;
365         while (*end && *end != '\r' && *end != '\n')
366           end++;
367
368         XTextExtents (bst->font, start, end-start,
369                       &dir, &ascent, &descent, &ov);
370         if (ov.width > max_width)
371           max_width = ov.width;
372         if (!*end) break;
373         start = end+1;
374       }
375
376   switch (bst->queue[bst->pos].type) {
377   case LEFT:
378   case LEFT_FULL:
379     bst->current_left = bst->left_margin + bst->xoff;
380     break;
381   case RIGHT:
382   case RIGHT_FULL:
383     bst->x = max_width - bst->right_margin - bst->xoff;
384     bst->current_left = bst->x;
385     break;
386   case CENTER:
387   case CENTER_FULL:
388     {
389       int w = (bst->xgwa.width - bst->left_margin - bst->right_margin -
390                max_width);
391       if (w < 0) w = 0;
392       bst->x = bst->left_margin + bst->xoff + (w / 2);
393       bst->current_left = bst->x;
394       break;
395     }
396   default:
397     abort();
398   }
399 }
400
401
402 static void
403 bst_crlf (struct bsod_state *bst)
404 {
405   int lh = bst->font->ascent + bst->font->descent;
406   bst->x = bst->current_left;
407   if (!bst->scroll_p ||
408       bst->y + lh < bst->xgwa.height - bst->bottom_margin - bst->yoff)
409     bst->y += lh;
410   else
411     {
412       int w = bst->xgwa.width  - bst->right_margin - bst->left_margin;
413       int h = bst->xgwa.height - bst->top_margin - bst->bottom_margin;
414       XCopyArea (bst->dpy, bst->window, bst->window, bst->gc,
415                  bst->left_margin + bst->xoff,
416                  bst->top_margin + bst->yoff + lh,
417                  w, h - lh,
418                  bst->left_margin + bst->xoff,
419                  bst->top_margin + bst->yoff);
420       XClearArea (bst->dpy, bst->window,
421                   bst->left_margin + bst->xoff,
422                   bst->top_margin + bst->yoff + h - lh, w, lh, False);
423     }
424 }
425
426
427 static void
428 draw_char (struct bsod_state *bst, char c)
429 {
430   if (!c)
431     abort();
432   else if (bst->crop_p && bst->y >=
433            (bst->xgwa.height - bst->bottom_margin - bst->yoff))
434     {
435       /* reached the bottom of the drawing area, and crop_p = True */
436       return;
437     }
438   else if (c == '\r')
439     {
440       bst->x = bst->current_left;
441     }
442   else if (c == '\n')
443     {
444       if (bst->macx_eol_kludge)
445         {
446           /* Special case for the weird way OSX crashes print newlines... */
447           XDrawImageString (bst->dpy, bst->window, bst->gc,
448                             bst->x, bst->y, " ", 1);
449           XDrawImageString (bst->dpy, bst->window, bst->gc,
450                             bst->x,
451                             bst->y + bst->font->ascent + bst->font->descent,
452                             " ", 1);
453         }
454       bst_crlf (bst);
455     }
456   else if (c == '\b')   /* backspace */
457     {
458       int cw = (bst->font->per_char
459                 ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
460                 : bst->font->min_bounds.width);
461       bst->x -= cw;
462       if (bst->x < bst->left_margin + bst->xoff)
463         bst->x = bst->left_margin + bst->xoff;
464     }
465   else
466     {
467       int dir, ascent, descent;
468       XCharStruct ov;
469       XTextExtents (bst->font, &c, 1, &dir, &ascent, &descent, &ov);
470
471       if (bst->wrap_p &&
472           bst->x + ov.width > bst->xgwa.width - bst->right_margin - bst->xoff)
473         bst_crlf (bst);
474
475       XDrawImageString (bst->dpy, bst->window, bst->gc,
476                         bst->x, bst->y, &c, 1);
477       bst->x += ov.width;
478     }
479 }
480
481
482 static long
483 bsod_pop (struct bsod_state *bst)
484 {
485   bsod_event_type type = bst->queue[bst->pos].type;
486
487   if (bst->draw_cb)
488     return bst->draw_cb (bst);
489
490   if (bst->pos < 0)   /* already done */
491     abort();
492
493   switch (type) {
494
495   case LEFT:   case LEFT_FULL:
496   case CENTER: case CENTER_FULL:
497   case RIGHT:  case RIGHT_FULL:
498     {
499       const char *s = (const char *) bst->queue[bst->pos].arg2;
500       char c;
501
502       if (! *s)
503         {
504           long delay = bst->line_delay;
505           bst->pos++;
506           bst->current_left = bst->left_margin + bst->xoff;
507           return delay;
508         }
509
510       if (! bst->queue[bst->pos].arg3)    /* "done once" */
511         {
512           position_for_text (bst, s);
513           bst->queue[bst->pos].arg4 = (void *) bst->queue[bst->pos].type;
514           bst->queue[bst->pos].type = LEFT;
515
516           if (type == CENTER_FULL ||
517               type == LEFT_FULL ||
518               type == RIGHT_FULL)
519             {
520               XSetForeground (bst->dpy, bst->gc, bst->bg);
521               XFillRectangle (bst->dpy, bst->window, bst->gc,
522                               0,
523                               bst->y - bst->font->ascent,
524                               bst->xgwa.width,
525                               bst->font->ascent + bst->font->descent);
526               XSetForeground (bst->dpy, bst->gc, bst->fg);
527             }
528         }
529
530       c = *s++;
531       draw_char (bst, c);
532       bst->queue[bst->pos].arg2 = (void *) s;
533       bst->queue[bst->pos].arg3 = (void *) 1;  /* "done once" */
534
535       return (c == '\r' || c == '\n'
536               ? bst->line_delay
537               : bst->char_delay);
538     }
539   case INVERT:
540     {
541       unsigned long swap = bst->fg;
542       bst->fg = bst->bg;
543       bst->bg = swap;
544       XSetForeground (bst->dpy, bst->gc, bst->fg);
545       XSetBackground (bst->dpy, bst->gc, bst->bg);
546       bst->pos++;
547       return 0;
548     }
549   case COLOR:
550     {
551       bst->fg = (unsigned long) bst->queue[bst->pos].arg1;
552       bst->bg = (unsigned long) bst->queue[bst->pos].arg2;
553       XSetForeground (bst->dpy, bst->gc, bst->fg);
554       XSetBackground (bst->dpy, bst->gc, bst->bg);
555       bst->pos++;
556       return 0;
557     }
558   case MOVETO:
559     {
560       bst->x = (long) bst->queue[bst->pos].arg1;
561       bst->y = (long) bst->queue[bst->pos].arg2;
562       bst->pos++;
563       return 0;
564     }
565   case RECT:
566     {
567       int f = (long) bst->queue[bst->pos].arg1;
568       int x = (long) bst->queue[bst->pos].arg2;
569       int y = (long) bst->queue[bst->pos].arg3;
570       int w = (long) bst->queue[bst->pos].arg4;
571       int h = (long) bst->queue[bst->pos].arg5;
572       if (f)
573         XFillRectangle (bst->dpy, bst->window, bst->gc, x, y, w, h);
574       else
575         XDrawRectangle (bst->dpy, bst->window, bst->gc, x, y, w, h);
576       bst->pos++;
577       return 0;
578     }
579   case LINE:
580     {
581       int x1 = (long) bst->queue[bst->pos].arg1;
582       int y1 = (long) bst->queue[bst->pos].arg2;
583       int x2 = (long) bst->queue[bst->pos].arg3;
584       int y2 = (long) bst->queue[bst->pos].arg4;
585       int t  = (long) bst->queue[bst->pos].arg5;
586       XGCValues gcv;
587       gcv.line_width = t;
588       XChangeGC (bst->dpy, bst->gc, GCLineWidth, &gcv);
589       XDrawLine (bst->dpy, bst->window, bst->gc, x1, y1, x2, y2);
590       bst->pos++;
591       return 0;
592     }
593   case COPY:
594   case PIXMAP:
595     {
596       int srcx = (long) bst->queue[bst->pos].arg1;
597       int srcy = (long) bst->queue[bst->pos].arg2;
598       int w    = (long) bst->queue[bst->pos].arg3;
599       int h    = (long) bst->queue[bst->pos].arg4;
600       int tox  = (long) bst->queue[bst->pos].arg5;
601       int toy  = (long) bst->queue[bst->pos].arg6;
602       XCopyArea (bst->dpy,
603                  (type == PIXMAP ? bst->pixmap : bst->window),
604                  bst->window, bst->gc,
605                  srcx, srcy, w, h, tox, toy);
606       bst->pos++;
607       return 0;
608     }
609   case IMG:
610     {
611       if (bst->img_loader) abort();
612       bst->img_loader = load_image_async_simple (0, bst->xgwa.screen,
613                                                  bst->window, bst->window,
614                                                  0, 0);
615       bst->pos++;
616       return 0;
617     }
618   case FONT:
619     {
620       switch ((long) bst->queue[bst->pos].arg1) {
621       case 0: bst->font = bst->fontA; break;
622       case 1: bst->font = bst->fontB; break;
623       case 2: bst->font = bst->fontC; break;
624       default: abort(); break;
625       }
626       XSetFont (bst->dpy, bst->gc, bst->font->fid);
627       bst->pos++;
628       return 0;
629     }
630   case PAUSE:
631     {
632       long delay = (long) bst->queue[bst->pos].arg1;
633       bst->pos++;
634       return delay;
635     }
636   case CHAR_DELAY:
637     {
638       bst->char_delay = (long) bst->queue[bst->pos].arg1;
639       bst->pos++;
640       return 0;
641     }
642   case LINE_DELAY:
643     {
644       bst->line_delay = (long) bst->queue[bst->pos].arg1;
645       bst->pos++;
646       return 0;
647     }
648   case MARGINS:
649     {
650       bst->left_margin  = (long) bst->queue[bst->pos].arg1;
651       bst->right_margin = (long) bst->queue[bst->pos].arg2;
652       bst->pos++;
653       return 0;
654     }
655   case VERT_MARGINS:
656     {
657       bst->top_margin    = (long) bst->queue[bst->pos].arg1;
658       bst->bottom_margin = (long) bst->queue[bst->pos].arg2;
659       bst->pos++;
660       return 0;
661     }
662   case CURSOR_BLOCK:
663   case CURSOR_LINE:
664     {
665       long delay = (long) bst->queue[bst->pos].arg1;
666       long count = (long) bst->queue[bst->pos].arg2;
667       int ox = bst->x;
668
669       if (type == CURSOR_BLOCK)
670         {
671           unsigned long swap = bst->fg;
672           bst->fg = bst->bg;
673           bst->bg = swap;
674           XSetForeground (bst->dpy, bst->gc, bst->fg);
675           XSetBackground (bst->dpy, bst->gc, bst->bg);
676           draw_char (bst, ' ');
677         }
678       else
679         {
680           draw_char (bst, (count & 1 ? ' ' : '_'));
681           draw_char (bst, ' ');
682         }
683
684       bst->x = ox;
685
686       count--;
687       bst->queue[bst->pos].arg2 = (void *) count;
688       if (count <= 0)
689         bst->pos++;
690
691       return delay;
692     }
693   case LOOP:
694     {
695       long off = (long) bst->queue[bst->pos].arg1;
696       bst->pos += off;
697       if (bst->pos < 0 || bst->pos >= bst->queue_size)
698         abort();
699       return 0;
700     }
701   case RESET:
702     {
703       int i;
704       for (i = 0; i < bst->queue_size; i++)
705         switch (bst->queue[i].type) {
706         case LEFT:   case LEFT_FULL:
707         case CENTER: case CENTER_FULL:
708         case RIGHT:  case RIGHT_FULL:
709           bst->queue[i].arg2 = bst->queue[i].arg1;
710           bst->queue[i].arg3 = 0;
711           bst->queue[i].type = (bsod_event_type) bst->queue[i].arg4;
712           break;
713         default: break;
714         }
715       bst->pos = 0;
716       return 0;
717     }
718   case CROP:
719     {
720       bst->crop_p = (long) bst->queue[bst->pos].arg1;
721       bst->pos++;
722       return 0;
723     }
724   case EOF:
725     {
726       bst->pos = -1;
727       return -1;
728     }
729   default:
730     break;
731   }
732   abort();
733 }
734
735
736 static struct bsod_state *
737 make_bsod_state (Display *dpy, Window window,
738                  const char *name, const char *class)
739 {
740   XGCValues gcv;
741   struct bsod_state *bst;
742   char buf1[1024], buf2[1024];
743   char buf3[1024], buf4[1024];
744   char buf5[1024], buf6[1024];
745   char buf7[1024], buf8[1024];
746   const char *font1, *font2, *font3, *font4;
747
748   bst = (struct bsod_state *) calloc (1, sizeof (*bst));
749   bst->queue_size = 10;
750   bst->queue = (struct bsod_event *) calloc (bst->queue_size,
751                                              sizeof (*bst->queue));
752   bst->dpy = dpy;
753   bst->window = window;
754   XGetWindowAttributes (dpy, window, &bst->xgwa);
755
756   /* If the window is small:
757        use ".font" if it is loadable, else use ".font2".
758
759      If the window is big:
760        use ".bigFont" if it is loadable, else use ".bigFont2".
761    */
762   if (
763 # ifdef HAVE_MOBILE
764       1
765 # else
766       bst->xgwa.height < 640
767 # endif
768       )
769     {
770       sprintf (buf1, "%.100s.font", name);
771       sprintf (buf2, "%.100s.font", class);
772       sprintf (buf3, "%.100s.font2", name);
773       sprintf (buf4, "%.100s.font2", class);
774     }
775   else
776     {
777       sprintf (buf1, "%.100s.bigFont", name);
778       sprintf (buf2, "%.100s.bigFont", class);
779       sprintf (buf3, "%.100s.bigFont2", name);
780       sprintf (buf4, "%.100s.bigFont2", class);
781     }
782   sprintf (buf5, "%.100s.fontB", name);
783   sprintf (buf6, "%.100s.fontB", class);
784   sprintf (buf7, "%.100s.fontC", name);
785   sprintf (buf8, "%.100s.fontC", class);
786
787   font1 = get_string_resource (dpy, buf1, buf2);
788   font2 = get_string_resource (dpy, buf3, buf4);
789   font3 = get_string_resource (dpy, buf5, buf6);
790   font4 = get_string_resource (dpy, buf7, buf8);
791
792   /* If there was no ".mode.font2" resource also look for ".font2".
793      Under real X11, the wildcard does this, so this is redundant,
794      but jwxyz needs it because it doesn't implement wildcards.
795    */
796 # define RES2(VAR, BUF1, BUF2) do {                          \
797     if (! VAR) {                                             \
798       VAR = get_string_resource (dpy,                        \
799                                  strchr (BUF1, '.') + 1,     \
800                                  strchr (BUF2, '.') + 1);    \
801     }} while(0)
802   RES2 (font1, buf1, buf2);
803   RES2 (font2, buf3, buf4);
804   RES2 (font3, buf5, buf6);
805   RES2 (font4, buf7, buf8);
806 #undef RES2
807
808   if (font1)
809     bst->font = XLoadQueryFont (dpy, font1);
810   if (! bst->font && font2)
811     bst->font = XLoadQueryFont (dpy, font2);
812
813   /* If neither of those worked, try some defaults. */
814
815   if (! bst->font)
816     bst->font = XLoadQueryFont (dpy,"-*-courier-bold-r-*-*-*-120-*-*-m-*-*-*");
817   if (! bst->font)
818     bst->font = XLoadQueryFont (dpy, "fixed");
819   if (! bst->font)
820     abort();
821
822   if (font3)
823     bst->fontB = XLoadQueryFont (dpy, font3);
824   if (font4)
825     bst->fontC = XLoadQueryFont (dpy, font4);
826
827   if (! bst->fontB) bst->fontB = bst->font;
828   if (! bst->fontC) bst->fontC = bst->font;
829
830   bst->fontA = bst->font;
831
832
833   gcv.font = bst->font->fid;
834
835   sprintf (buf1, "%.100s.foreground", name);
836   sprintf (buf2, "%.100s.Foreground", class);
837   bst->fg = gcv.foreground = get_pixel_resource (dpy, bst->xgwa.colormap,
838                                                  buf1, buf2);
839   sprintf (buf1, "%.100s.background", name);
840   sprintf (buf2, "%.100s.Background", class);
841   bst->bg = gcv.background = get_pixel_resource (dpy, bst->xgwa.colormap,
842                                                  buf1, buf2);
843   bst->gc = XCreateGC (dpy, window, GCFont|GCForeground|GCBackground, &gcv);
844
845 #ifdef HAVE_JWXYZ
846   jwxyz_XSetAntiAliasing (dpy, bst->gc, True);
847 #endif
848
849 # ifdef USE_IPHONE
850   /* Stupid iPhone X bezel.
851      #### This is the worst of all possible ways to do this!
852    */
853   if (bst->xgwa.width == 2436 || bst->xgwa.height == 2436) {
854     if (bst->xgwa.width > bst->xgwa.height)
855       bst->xoff = 96;
856     else
857       bst->yoff = 96;
858   }
859 # endif
860
861   bst->left_margin = bst->right_margin = 10;
862   bst->x = bst->left_margin + bst->xoff;
863   bst->y = bst->font->ascent + bst->left_margin + bst->yoff;
864
865   XSetWindowBackground (dpy, window, gcv.background);
866   return bst;
867 }
868
869
870 static void
871 free_bsod_state (struct bsod_state *bst)
872 {
873   int i;
874
875   if (bst->free_cb)
876     bst->free_cb (bst);
877   if (bst->pixmap)
878     XFreePixmap(bst->dpy, bst->pixmap);
879
880   XFreeFont (bst->dpy, bst->font);
881   XFreeGC (bst->dpy, bst->gc);
882
883   for (i = 0; i < bst->queue_size; i++)
884     switch (bst->queue[i].type) {
885     case LEFT:   case LEFT_FULL:
886     case RIGHT:  case RIGHT_FULL:
887     case CENTER: case CENTER_FULL:
888       free ((char *) bst->queue[i].arg1);
889       break;
890     default:
891       break;
892     }
893
894   free (bst->queue);
895   free (bst);
896 }
897
898
899 static Pixmap
900 double_pixmap (Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
901                int pix_w, int pix_h)
902 {
903   int x, y;
904   Pixmap p2 = XCreatePixmap(dpy, pixmap, pix_w*2, pix_h*2, depth);
905   XImage *i1 = XGetImage(dpy, pixmap, 0, 0, pix_w, pix_h, ~0L, ZPixmap);
906   XImage *i2 = XCreateImage(dpy, visual, depth, ZPixmap, 0, 0,
907                             pix_w*2, pix_h*2, 8, 0);
908   i2->data = (char *) calloc(i2->height, i2->bytes_per_line);
909   for (y = 0; y < pix_h; y++)
910     for (x = 0; x < pix_w; x++)
911       {
912         unsigned long p = XGetPixel(i1, x, y);
913         XPutPixel(i2, x*2,   y*2,   p);
914         XPutPixel(i2, x*2+1, y*2,   p);
915         XPutPixel(i2, x*2,   y*2+1, p);
916         XPutPixel(i2, x*2+1, y*2+1, p);
917       }
918   free(i1->data); i1->data = 0;
919   XDestroyImage(i1);
920   XPutImage(dpy, p2, gc, i2, 0, 0, 0, 0, i2->width, i2->height);
921   free(i2->data); i2->data = 0;
922   XDestroyImage(i2);
923   XFreePixmap(dpy, pixmap);
924   return p2;
925 }
926
927
928 /*****************************************************************************
929  *****************************************************************************/
930
931 static struct bsod_state *
932 windows_31 (Display *dpy, Window window)
933 {
934   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
935
936   bst->xoff = bst->left_margin = bst->right_margin = 0;
937
938   BSOD_INVERT (bst);
939   BSOD_TEXT   (bst, CENTER, "Windows\n");
940   BSOD_INVERT (bst);
941   BSOD_TEXT   (bst, CENTER,
942                "A fatal exception 0E has occured at F0AD:42494C4C\n"
943                "the current application will be terminated.\n"
944                "\n"
945                "* Press any key to terminate the current application.\n"
946                "* Press CTRL+ALT+DELETE again to restart your computer.\n"
947                "  You will lose any unsaved information in all applications.\n"
948                "\n"
949                "\n");
950   BSOD_TEXT   (bst, CENTER, "Press any key to continue");
951
952   bst->y = ((bst->xgwa.height - bst->yoff -
953              ((bst->font->ascent + bst->font->descent) * 9))
954             / 2);
955
956   XClearWindow (dpy, window);
957   return bst;
958 }
959
960 static struct bsod_state *
961 vmware (Display *dpy, Window window)
962 {
963   struct bsod_state *bst = make_bsod_state (dpy, window, "vmware", "VMware");
964
965   unsigned long fg = bst->fg;
966   unsigned long bg = bst->bg;
967   unsigned long fg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
968                                           "vmware.foreground2",
969                                           "vmware.foreground");
970   BSOD_COLOR (bst, fg2, bg);
971   BSOD_TEXT   (bst, LEFT,
972                 "VMware ESX Server [Releasebuild-98103]\n");
973   BSOD_COLOR (bst, fg, bg);
974   BSOD_TEXT   (bst, LEFT,
975                 "PCPU 1 locked up. Failed to ack TLB invalidate.\n"
976                 "frame=0x3a37d98 ip=0x625e94 cr2=0x0 cr3=0x40c66000 cr4=0x16c\n"
977                 "es=0xffffffff ds=0xffffffff fs=0xffffffff gs=0xffffffff\n"
978                 "eax=0xffffffff ebx=0xffffffff ecx=0xffffffff edx=0xffffffff\n"
979                 "ebp=0x3a37ef4 esi=0xffffffff edi=0xffffffff err=-1 eflags=0xffffffff\n"
980                 "*0:1037/helper1-4 1:1107/vmm0:Fagi 2:1121/vmware-vm 3:1122/mks:Franc\n"
981                 "0x3a37ef4:[0x625e94]Panic+0x17 stack: 0x833ab4, 0x3a37f10, 0x3a37f48\n"
982                 "0x3a37f04:[0x625e94]Panic+0x17 stack: 0x833ab4, 0x1, 0x14a03a0\n"
983                 "0x3a37f48:[0x64bfa4]TLBDoInvalidate+0x38f stack: 0x3a37f54, 0x40, 0x2\n"
984                 "0x3a37f70:[0x66da4d]XMapForceFlush+0x64 stack: 0x0, 0x4d3a, 0x0\n"
985                 "0x3a37fac:[0x652b8b]helpFunc+0x2d2 stack: 0x1, 0x14a4580, 0x0\n"
986                 "0x3a37ffc:[0x750902]CpuSched_StartWorld+0x109 stack: 0x0, 0x0, 0x0\n"
987                 "0x3a38000:[0x0]blk_dev+0xfd76461f stack: 0x0, 0x0, 0x0\n"
988                 "VMK uptime: 7:05:43:45.014 TSC: 1751259712918392\n"
989                 "Starting coredump to disk\n");
990   BSOD_CHAR_DELAY (bst, 10000);         
991   BSOD_TEXT (bst, LEFT, "using slot 1 of 1... ");
992   BSOD_CHAR_DELAY (bst, 300000);
993   BSOD_TEXT (bst, LEFT, "9876");
994   BSOD_CHAR_DELAY (bst, 3000000);
995   BSOD_TEXT (bst, LEFT, "66665");
996   BSOD_CHAR_DELAY (bst, 100000);
997   BSOD_TEXT (bst, LEFT, "4321");
998   BSOD_CHAR_DELAY (bst, 0);
999   BSOD_TEXT (bst, LEFT, "Disk dump successfull.\n"
1000                 "Waiting for Debugger (world 1037)\n"
1001                 "Debugger is listening on serial port ...\n");
1002   BSOD_CHAR_DELAY (bst, 10000);
1003   BSOD_TEXT (bst, LEFT, "Press Escape to enter local debugger\n");
1004   BSOD_CHAR_DELAY (bst, 10000);
1005   BSOD_TEXT (bst, LEFT, "Remote debugger activated. Local debugger no longer available.\n");
1006
1007 /*  BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999);*/
1008                 
1009 /*  bst->y = ((bst->xgwa.height - bst->yoff -
1010              ((bst->font->ascent + bst->font->descent) * 9))
1011             / 2);*/
1012
1013   XClearWindow (dpy, window);
1014   return bst;
1015 }
1016
1017
1018
1019 static struct bsod_state *
1020 windows_nt (Display *dpy, Window window)
1021 {
1022   struct bsod_state *bst = make_bsod_state (dpy, window, "nt", "NT");
1023
1024   BSOD_TEXT (bst, LEFT,
1025    "*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
1026    "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
1027    "\n"
1028    "Dll Base Date Stamp - Name             Dll Base Date Stamp - Name\n"
1029    "80100000 2be154c9 - ntoskrnl.exe       80400000 2bc153b0 - hal.dll\n"
1030    "80258000 2bd49628 - ncrc710.sys        8025c000 2bd49688 - SCSIPORT.SYS \n"
1031    "80267000 2bd49683 - scsidisk.sys       802a6000 2bd496b9 - Fastfat.sys\n"
1032    "fa800000 2bd49666 - Floppy.SYS         fa810000 2bd496db - Hpfs_Rec.SYS\n"
1033    "fa820000 2bd49676 - Null.SYS           fa830000 2bd4965a - Beep.SYS\n"
1034    "fa840000 2bdaab00 - i8042prt.SYS       fa850000 2bd5a020 - SERMOUSE.SYS\n"
1035    "fa860000 2bd4966f - kbdclass.SYS       fa870000 2bd49671 - MOUCLASS.SYS\n"
1036    "fa880000 2bd9c0be - Videoprt.SYS       fa890000 2bd49638 - NCC1701E.SYS\n"
1037    "fa8a0000 2bd4a4ce - Vga.SYS            fa8b0000 2bd496d0 - Msfs.SYS\n"
1038    "fa8c0000 2bd496c3 - Npfs.SYS           fa8e0000 2bd496c9 - Ntfs.SYS\n"
1039    "fa940000 2bd496df - NDIS.SYS           fa930000 2bd49707 - wdlan.sys\n"
1040    "fa970000 2bd49712 - TDI.SYS            fa950000 2bd5a7fb - nbf.sys\n"
1041    "fa980000 2bd72406 - streams.sys        fa9b0000 2bd4975f - ubnb.sys\n"
1042    "fa9c0000 2bd5bfd7 - usbser.sys         fa9d0000 2bd4971d - netbios.sys\n"
1043    "fa9e0000 2bd49678 - Parallel.sys       fa9f0000 2bd4969f - serial.SYS\n"
1044    "faa00000 2bd49739 - mup.sys            faa40000 2bd4971f - SMBTRSUP.SYS\n"
1045    "faa10000 2bd6f2a2 - srv.sys            faa50000 2bd4971a - afd.sys\n"
1046    "faa60000 2bd6fd80 - rdr.sys            faaa0000 2bd49735 - bowser.sys\n"
1047    "\n"
1048    "Address dword dump Dll Base                                      - Name\n"
1049    "801afc20 80106fc0 80106fc0 00000000 00000000 80149905 : "
1050      "fa840000 - i8042prt.SYS\n"
1051    "801afc24 80149905 80149905 ff8e6b8c 80129c2c ff8e6b94 : "
1052      "8025c000 - SCSIPORT.SYS\n"
1053    "801afc2c 80129c2c 80129c2c ff8e6b94 00000000 ff8e6b94 : "
1054      "80100000 - ntoskrnl.exe\n"
1055    "801afc34 801240f2 80124f02 ff8e6df4 ff8e6f60 ff8e6c58 : "
1056      "80100000 - ntoskrnl.exe\n"
1057    "801afc54 80124f16 80124f16 ff8e6f60 ff8e6c3c 8015ac7e : "
1058      "80100000 - ntoskrnl.exe\n"
1059    "801afc64 8015ac7e 8015ac7e ff8e6df4 ff8e6f60 ff8e6c58 : "
1060      "80100000 - ntoskrnl.exe\n"
1061    "801afc70 80129bda 80129bda 00000000 80088000 80106fc0 : "
1062      "80100000 - ntoskrnl.exe\n"
1063    "\n"
1064    "Kernel Debugger Using: COM2 (Port 0x2f8, Baud Rate 19200)\n"
1065    "Restart and set the recovery options in the system control panel\n"
1066    "or the /CRASHDEBUG system start option. If this message reappears,\n"
1067    "contact your system administrator or technical support group."
1068    );
1069
1070   bst->line_delay = 750;
1071
1072   XClearWindow (dpy, window);
1073   return bst;
1074 }
1075
1076
1077 static struct bsod_state *
1078 windows_2k (Display *dpy, Window window)
1079 {
1080   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
1081
1082   BSOD_TEXT (bst, LEFT,
1083     "*** STOP: 0x000000D1 (0xE1D38000,0x0000001C,0x00000000,0xF09D42DA)\n"
1084     "DRIVER_IRQL_NOT_LESS_OR_EQUAL \n"
1085     "\n"
1086     "*** Address F09D42DA base at F09D4000, DateStamp 39f459ff - CRASHDD.SYS\n"
1087     "\n"
1088     "Beginning dump of physical memory\n");
1089   BSOD_PAUSE (bst, 4000000);
1090   BSOD_TEXT (bst, LEFT,
1091     "Physical memory dump complete. Contact your system administrator or\n"
1092     "technical support group.\n");
1093
1094   bst->left_margin = 40;
1095   bst->y = (bst->font->ascent + bst->font->descent) * 10;
1096   bst->line_delay = 750;
1097
1098   XClearWindow (dpy, window);
1099   return bst;
1100 }
1101
1102
1103 static struct bsod_state *
1104 windows_me (Display *dpy, Window window)
1105 {
1106   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
1107
1108   BSOD_TEXT (bst, LEFT,
1109     "Windows protection error.  You need to restart your computer.\n\n"
1110     "System halted.");
1111   BSOD_CURSOR (bst, CURSOR_LINE, 120000, 999999);
1112
1113   bst->left_margin = 40;
1114   bst->y = ((bst->xgwa.height - bst->yoff -
1115              ((bst->font->ascent + bst->font->descent) * 3))
1116             / 2);
1117
1118   XClearWindow (dpy, window);
1119   return bst;
1120 }
1121
1122
1123 static struct bsod_state *
1124 windows_xp (Display *dpy, Window window)
1125 {
1126   struct bsod_state *bst = make_bsod_state (dpy, window, "windows", "Windows");
1127
1128   BSOD_TEXT (bst, LEFT,  /* From Wm. Rhodes <xscreensaver@27.org> */
1129       "A problem has been detected and windows has been shut down to prevent "
1130       "damage\n"
1131       "to your computer.\n"
1132       "\n"
1133       "If this is the first time you've seen this Stop error screen,\n"
1134       "restart your computer. If this screen appears again, follow\n"
1135       "these steps:\n"
1136       "\n"
1137       "Check to be sure you have adequate disk space. If a driver is\n"
1138       "identified in the Stop message, disable the driver or check\n"
1139       "with the manufacturer for driver updates. Try changing video\n"
1140       "adapters.\n"
1141       "\n"
1142       "Check with your hardware vendor for any BIOS updates. Disable\n"
1143       "BIOS memory options such as caching or shadowing. If you need\n"
1144       "to use Safe Mode to remove or disable components, restart your\n"
1145       "computer, press F8 to select Advanced Startup Options, and then\n"
1146       "select Safe Mode.\n"
1147       "\n"
1148       "Technical information:\n"
1149       "\n"
1150       "*** STOP: 0x0000007E (0xC0000005,0xF88FF190,0x0xF8975BA0,0xF89758A0)\n"
1151       "\n"
1152       "\n"
1153       "***  EPUSBDSK.sys - Address F88FF190 base at FF88FE000, datestamp "
1154       "3b9f3248\n"
1155       "\n"
1156       "Beginning dump of physical memory\n");
1157   BSOD_PAUSE (bst, 4000000);
1158   BSOD_TEXT (bst, LEFT,
1159       "Physical memory dump complete.\n"
1160       "Contact your system administrator or technical support group for "
1161       "further\n"
1162       "assistance.\n");
1163
1164   XClearWindow (dpy, window);
1165   return bst;
1166 }
1167
1168
1169 static struct bsod_state *
1170 windows_lh (Display *dpy, Window window)
1171 {
1172   struct bsod_state *bst =
1173     make_bsod_state (dpy, window, "windowslh", "WindowsLH");
1174
1175   unsigned long fg = bst->fg;
1176   unsigned long bg = bst->bg;
1177   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
1178                                           "windowslh.background2",
1179                                           "WindowsLH.Background");
1180
1181   /* The "RSOD" that appeared with "Windows Longhorn 5048.050401-0536_x86fre"
1182      As reported by http://joi.ito.com/RedScreen.jpg
1183    */
1184   BSOD_COLOR (bst, bg, bg2);
1185   BSOD_TEXT (bst, CENTER_FULL, "Windows Boot Error\n");
1186   BSOD_COLOR (bst, fg, bg);
1187   BSOD_TEXT (bst, CENTER,
1188      "\n"
1189      "Windows Boot Manager has experienced a problem.\n"
1190      "\n"
1191      "\n"
1192      "    Status: 0xc000000f\n"
1193      "\n"
1194      "\n"
1195      "\n"
1196      "    Info: An error occurred transferring exectuion."  /* (sic) */
1197      "\n"
1198      "\n"
1199      "\n"
1200      "You can try to recover the system with the Microsoft Windows "
1201      "System Recovery\n"
1202      "Tools. (You might need to restart the system manually.)\n"
1203      "\n"
1204      "If the problem continues, please contact your system administrator "
1205      "or computer\n"
1206      "manufacturer.\n"
1207      );
1208   BSOD_MOVETO (bst, bst->left_margin + bst->xoff,
1209                bst->xgwa.height - bst->yoff - bst->font->descent);
1210   BSOD_COLOR (bst, bg, bg2);
1211   BSOD_TEXT (bst, LEFT_FULL, " SPACE=Continue\n");
1212
1213   bst->y = bst->font->ascent;
1214
1215   XClearWindow (dpy, window);
1216   return bst;
1217 }
1218
1219
1220 static struct bsod_state *
1221 windows_10_update (Display *dpy, Window window)
1222 {
1223   struct bsod_state *bst =
1224     make_bsod_state (dpy, window, "win10", "Win10");
1225   const char *fmt  = "Working on updates  %d%%";
1226   char        line1[255];
1227   const char *line2 = "Don't turn off your PC. This will take a while.";
1228   const char *line3 = "Your PC will restart several times.";
1229   int line_height = bst->fontA->ascent + bst->fontA->descent;
1230   int y1 = bst->xgwa.height / 2 - line_height * 4;
1231   int y2 = bst->xgwa.height - bst->yoff - line_height * 3;
1232   int pct;
1233
1234   /* TODO: win10_spinner.gif goes at (y - line_height * 2 - 64). */
1235
1236   for (pct = 0; pct < 98; pct++)
1237     {
1238       BSOD_MOVETO (bst, 0, y1);
1239       sprintf (line1, fmt, pct);
1240       BSOD_TEXT (bst, CENTER, line1);
1241       BSOD_MOVETO (bst, 0, y1 + line_height);
1242       BSOD_TEXT (bst, CENTER, line2);
1243       BSOD_MOVETO (bst, 0, y2);
1244       BSOD_TEXT (bst, CENTER, line3);
1245       BSOD_PAUSE (bst, 200000 + (random() % 3000000) + (random() % 3000000));
1246     }
1247
1248   XClearWindow (dpy, window);
1249   return bst;
1250 }
1251
1252
1253 static struct bsod_state *
1254 windows_10 (Display *dpy, Window window)
1255 {
1256   struct bsod_state *bst =
1257     make_bsod_state (dpy, window, "win10", "Win10");
1258
1259   int qr_width  = 41;
1260   int qr_height = 41;
1261   static const unsigned char qr_bits[] = {
1262     0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,
1263     0x03,0x9A,0x70,0xEE,0x80,0x01,0xFB,0x22,0xAA,0xA6,0xBE,0x01,
1264     0x8B,0x8E,0x74,0xE7,0xA2,0x01,0x8B,0xEE,0x42,0xC4,0xA2,0x01,
1265     0x8B,0x42,0x6E,0xED,0xA2,0x01,0xFB,0xDA,0x63,0xA6,0xBE,0x01,
1266     0x03,0xAA,0xAA,0xAA,0x80,0x01,0xFF,0x8B,0xD8,0x9D,0xFF,0x01,
1267     0x63,0x62,0xDA,0x1B,0x98,0x01,0x6F,0x67,0x98,0x9F,0xBC,0x01,
1268     0x4F,0xCC,0x55,0x81,0x83,0x01,0xB7,0x6D,0xFF,0x68,0xB2,0x01,
1269     0xC3,0x10,0x87,0x8B,0x96,0x01,0x6F,0xB1,0x91,0x58,0x94,0x01,
1270     0xE3,0x36,0x88,0x84,0xB8,0x01,0x83,0x9B,0xFE,0x59,0xD7,0x01,
1271     0x3B,0x74,0x98,0x5C,0xB4,0x01,0x37,0x75,0xDC,0x91,0xA6,0x01,
1272     0x77,0xDE,0x01,0x54,0xBA,0x01,0xBB,0x6D,0x8B,0xB9,0xB5,0x01,
1273     0x1F,0x06,0xBD,0x9B,0xB4,0x01,0xD3,0xBD,0x91,0x19,0x84,0x01,
1274     0x0B,0x20,0xD8,0x91,0xB4,0x01,0x33,0x95,0xBC,0x0A,0xD5,0x01,
1275     0xB3,0x60,0xDC,0xD9,0xB6,0x01,0xEF,0x77,0x18,0x09,0xA4,0x01,
1276     0xA3,0xC2,0x95,0x51,0xB2,0x01,0xDF,0x63,0xDB,0xBE,0xB3,0x01,
1277     0x03,0x08,0xC9,0x09,0xF0,0x01,0xFF,0xA3,0x19,0xBD,0xFB,0x01,
1278     0x03,0x2E,0x84,0xA5,0xAA,0x01,0xFB,0x9A,0xFC,0x9B,0xBB,0x01,
1279     0x8B,0x7E,0x9C,0x1D,0xB0,0x01,0x8B,0x6E,0x58,0xA1,0xDB,0x01,
1280     0x8B,0xDA,0xD5,0x65,0xA2,0x01,0xFB,0x72,0xFB,0xE9,0xF0,0x01,
1281     0x03,0x02,0x99,0x3B,0xB3,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,
1282     0xFF,0xFF,0xFF,0xFF,0xFF,0x01};
1283   Pixmap pixmap;
1284
1285   const char *lines[] = {
1286     ":(\n",
1287     "\n",
1288     "Your PC ran into a problem and needs to restart. We're just\n",
1289     "collecting some error info, and then we'll restart for you.\n",
1290     "\n",
1291     "\n",
1292     "\n",
1293     "For more information about this issue and\n",
1294     "possible fixes, visit\n",
1295 /*  "https://www.jwz.org/xscreensaver\n",*/
1296     "http://youtu.be/-RjmN9RZyr4\n",
1297     "\n",
1298     "If you call a support person, give them this info:\n",
1299     "Stop code CRITICAL_PROCESS_DIED",
1300  };
1301   int i, y = 0, y0 = 0;
1302   int line_height0 = bst->fontB->ascent;
1303   int line_height1 = bst->fontA->ascent + bst->fontA->descent;
1304   int line_height2 = bst->fontC->ascent + bst->fontC->descent;
1305   int line_height = line_height0;
1306   int top, left0, left;
1307   int stop = 60 + (random() % 39);
1308
1309   if (!(random() % 7))
1310     return windows_10_update (dpy, window);
1311
1312
1313   line_height1 *= 1.3;
1314   line_height2 *= 1.5;
1315
1316   top = ((bst->xgwa.height - bst->yoff
1317           - (line_height0 * 1 +
1318              line_height1 * 6 +
1319              line_height2 * 6))
1320          / 2);
1321
1322   {
1323     int dir, ascent, descent;
1324     XCharStruct ov;
1325     const char *s = lines[2];
1326     XTextExtents (bst->fontA, s, strlen(s),
1327                   &dir, &ascent, &descent, &ov);
1328     left = left0 = (bst->xgwa.width - ov.width) / 2;
1329   }
1330
1331   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) qr_bits,
1332                                         qr_width, qr_height,
1333                                         bst->fg, bst->bg, bst->xgwa.depth);
1334   for (i = 0; i < 2; i++)
1335     {
1336       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
1337                               pixmap, qr_width, qr_height);
1338       qr_width *= 2;
1339       qr_height *= 2;
1340     }
1341   bst->pixmap = pixmap;
1342
1343   y = top;
1344   line_height = line_height0;
1345   BSOD_FONT (bst, 1);
1346   for (i = 0; i < countof(lines); i++)
1347     {
1348       BSOD_MOVETO (bst, left, y);
1349       BSOD_TEXT (bst, LEFT, lines[i]);
1350       y += line_height;
1351       if (i == 0)
1352         {
1353           BSOD_FONT (bst, 0);
1354           line_height = line_height1;
1355         }
1356       else if (i == 4)
1357         {
1358           y0 = y;
1359           y += line_height / 2;
1360           BSOD_PIXMAP (bst, 0, 0, qr_width, qr_height, left, y + line_height1);
1361           BSOD_FONT (bst, 2);
1362           line_height = line_height2;
1363           left += qr_width + line_height2 / 2;
1364 # ifdef HAVE_MOBILE
1365           y -= 14;
1366 # endif
1367         }
1368     }
1369
1370   left = left0;
1371   BSOD_FONT (bst, 0);
1372   for (i = 0; i <= stop; i++)
1373     {
1374       char buf[100];
1375       sprintf (buf, "%d%% complete", i);
1376       BSOD_MOVETO (bst, left, y0);
1377       BSOD_TEXT (bst, LEFT, buf);
1378       BSOD_PAUSE (bst, 85000);
1379     }
1380   BSOD_PAUSE (bst, 3000000);
1381
1382   XClearWindow (dpy, window);
1383   return bst;
1384 }
1385
1386
1387 static struct bsod_state *
1388 windows_other (Display *dpy, Window window)
1389 {
1390   /* Lump all of the 2K-ish crashes together and select them randomly...
1391    */
1392   int which = (random() % 4);
1393   switch (which) {
1394   case 0: return windows_2k (dpy, window); break;
1395   case 1: return windows_me (dpy, window); break;
1396   case 2: return windows_xp (dpy, window); break;
1397   case 3: return windows_lh (dpy, window); break;
1398   default: abort(); break;
1399   }
1400 }
1401
1402 /* Windows and Apple2 ransomware.
1403  */
1404 static struct bsod_state *apple2ransomware (Display *, Window);
1405
1406 static struct bsod_state *
1407 windows_ransomware (Display *dpy, Window window)
1408 {
1409   struct bsod_state *bst = make_bsod_state (dpy, window,
1410                                             "ransomware", "Ransomware");
1411   char buf[1024];
1412
1413   int pix_w = 0, pix_h = 0;
1414   Pixmap pixmap = xpm_data_to_pixmap (dpy, window,
1415                                       (char **) (ransomware_xpm),
1416                                       &pix_w, &pix_h, 0);
1417
1418   /* Don't start the countdown from the start, advance the deadline by 3 - 30
1419      hours */
1420   int advance_deadline = (random() % 97200) + 10800;
1421
1422   time_t now = time(NULL);
1423   const time_t stage1_deadline = now + 259200 - advance_deadline; /* 3 days */
1424   const time_t stage2_deadline = now + 604800 - advance_deadline; /* 7 days */
1425   char stage1_deadline_str[25], stage2_deadline_str[25];
1426   char countdown_str[16];
1427   int stage1_countdown_y, stage2_countdown_y;
1428   int countdown_d, countdown_h, countdown_m, countdown_s, countdown_r;
1429   const int line_height = bst->font->ascent + bst->font->descent;
1430   int i;
1431
1432   const char *currencies[] = {
1433     "Blitcoin",
1434     "clicks",
1435     "Ass Pennies",
1436     "Dollary-doos",
1437     "Dunning-Krugerrands",
1438     "Dunning-Krugerrands",
1439     "Dunning-Krugerrands",
1440     "Dunning-Krugerrands",
1441     "Dunning-Krugerrands",
1442     "gift certificates",
1443     "secret sauce",
1444     "Tribbles",
1445   };
1446
1447   const char *currency = currencies[random() % countof(currencies)];
1448
1449   const char *header_quips[] = {
1450     "Oops, your screens have been encrypted!",
1451     "Oops, your screens have been encrypted!",
1452     "Oops, your screens have been encrypted!",
1453     "Oops, your screens have been encrypted!",
1454     "Oops, your screen have encrypted!",
1455     "Oops, you're screens have been encrypted!",
1456     "Oops, your screens have been encrupted!",
1457     "Oops, your screens have been encrumpet!",
1458     "Oops, your screens have been encrusted!",
1459     "If you don't pay this ransom, then you are a theif!",
1460     "Your screen was subject to the laws of mathomatics!",
1461     "Oops, your screen was shaved by Occam's Razor!",
1462     "Oops, your screen was perturbated by Langford's Basilisk!",
1463     "Your screen is now stored as Snapchat messages!",
1464     "Oops, your screen is now stored on Betamax!",
1465     "Oops, your screen is now in the clown!",
1466     "Oops, your screen has been deprecated!",
1467     "Oops, you're screen was seized by the FBI!",
1468     "All your screen was shared with your coworkers!",
1469     "All your screen are belong to us.",
1470     "Well actually, your screen isn't needed anymore.",
1471     "u just got popped with some 0day shit!!",
1472     "M'lady,",
1473   };
1474
1475   const char *header_quip = header_quips[random() % countof(header_quips)];
1476
1477   /* You got this because... */
1478   const char *excuse_quips[] = {
1479     "all human actions are equivalent and all are on principle doomed "
1480     "to failure",
1481     "you hold a diverse portfolio of cryptocurrencies",
1482     "you need to get in on ransomware futures at the ground floor",
1483     "your flight was overbooked",
1484     "you did not apply the security update for bugs NSA keys secret from "
1485     "Microsoft in your Windows(R) operating system",
1486     "you are bad and you should feel bad",
1487     "you used the wifi at defcon",
1488     "you lack official Clown Strike[TM] threaty threat technology",
1489   };
1490
1491   const char *excuse_quip = excuse_quips[random() % countof(excuse_quips)];
1492
1493   /* WELL ACTUALLY, screensavers aren't really nescessary anymore because... */
1494   const char *screensaver_quips[] = {
1495     "I read it on hacker news",
1496     "that's official Debian policy now",
1497     "that is the official policy of United Airlines",
1498     "they cause global warming",
1499     "they lack an eternal struggle",
1500     "they lack a vapid dichotomy",
1501     "those electrons could be used for gold farming instead",
1502     "you can make more money in art exhibitions",
1503   };
1504
1505   const char *screensaver_quip =
1506     screensaver_quips[random() % countof(screensaver_quips)];
1507
1508   /* Positions of UI elements. Layout:
1509
1510   +---------+-+---------------------------------------+
1511   |   LOGO  | |               HEADER                  |
1512   |         | |---------------------------------------|
1513   |         | | NOTE TEXT                             |
1514   |   DEAD  | |                                       |
1515   |   LINE  | |                                       |
1516   |  TIMERS | |                                       |
1517   |         | |                                       |
1518   |         | |                                       |
1519   |         | |                                       |
1520   |         | |                                       |
1521   |         | |                                       |
1522   +---------+ |                                       |
1523   | LINKS   | +---------------------------------------+
1524   | LINKS   | | FOOTER                                |
1525   +---------+-+---------------------------------------+
1526
1527   The right side of the UI maximises to available width.
1528   The note text maximises to available height.
1529   The logo, header and timers are anchored to the top left of the window.
1530   The links and footer are anchored to the bottom left of the window.
1531   The entire window is a fixed 4:3 scale, with a minimum margin around it.
1532   */
1533
1534   /* Minimum margin around the window */
1535   int margin_size = 50;
1536
1537   /* Right side of window (header, ransom note, BTC address, buttons) */
1538   const int right_pane_x = 270;
1539   /* "oops" header */
1540   const int header_y = 5;
1541   /* Ransom note */
1542   const int ransom_y = 40;
1543   /* Footer area */
1544   const int footer_height = 100;
1545
1546   /* Left pane (deadlines, countdown, links) */
1547   const int left_pane_width = right_pane_x - 5;
1548   /* Logo (shown at top left corner) */
1549   int logo_x = (left_pane_width - pix_w) / 2;
1550   int logo_y = 10;
1551   /* Deadline position */
1552   const int deadline_y = 130;
1553   /* Links height */
1554   const int links_height = 100;
1555   const int links_x = 20;
1556
1557   /* main window text */
1558   unsigned long fg = bst->fg;
1559   unsigned long bg = bst->bg;
1560   /* ransom note */
1561   unsigned long fg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
1562                                           "ransomware.foreground2",
1563                                           "Ransomware.Foreground");
1564   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
1565                                           "ransomware.background2",
1566                                           "Ransomware.Background");
1567   /* buttons */
1568   unsigned long fg3 = get_pixel_resource (dpy, bst->xgwa.colormap,
1569                                           "ransomware.foreground3",
1570                                           "Ransomware.Foreground");
1571   unsigned long bg3 = get_pixel_resource (dpy, bst->xgwa.colormap,
1572                                           "ransomware.background3",
1573                                           "Ransomware.Background");
1574   /* links */
1575   unsigned long link = get_pixel_resource (dpy, bst->xgwa.colormap,
1576                                            "ransomware.link",
1577                                            "Ransomware.Foreground");
1578   /* headers */
1579   unsigned long theader = get_pixel_resource (dpy, bst->xgwa.colormap,
1580                                               "ransomware.timerheader",
1581                                               "Ransomware.Foreground");
1582
1583   const char *lines[] = {
1584     "*What Happened To My Computer?\n",
1585     "Your important pixels are paintcrypted. All of your documents, photos, ",
1586     "videos, databases, icons, dick pics are not accessible because they ",
1587     "have been bitblted. Maybe you are looking for a way to get them back, ",
1588     "but don't waste your time. Nobody can recover your pixels without our ",
1589     "pointer motion clicker services.\n",
1590     "\n",
1591     "*Can I Recover My Important Dick Pix?\n",
1592     "Yes. We guarantee that you can recover them safely and easily. But you ",
1593     "not have much time.\n",
1594     "You can expose some files for free. Try it now by pressing <The Any ",
1595     "Key>.\n",
1596     "But if you want to unsave all your screens, then you need to pay. ",
1597     "You have only 3 days to click. After that the clicks will double. ",
1598     "After 7 days your pixels will be gone forever.\n",
1599     "We will have free events for cheapskates who can't pay in 6 months, ",
1600     "long after all the pixels are xored.\n",
1601     "\n",
1602     "*How do I pay?\n",
1603     "Payment is accepted in ", "[C]",
1604     " only. For more information, press <About ", "[C]", ">.",
1605     " Please check the current price of ", "[C]", " and buy some ", "[C]",
1606     ". For more information, press <How to buy ", "[C]", ">.\n",
1607     "And send the correct amount to the address specified below. After your ",
1608     "payment, press <Check Payment>. Best time to check: 4-6am, Mon-Fri.\n",
1609     "\n",
1610     "*Why Did I Get This?\n",
1611     "You got this because ", "[Q]",
1612     ". Also you didn't click hard enough and now Tinkerbelle is dead.\n",
1613     "\n",
1614     "*But Aren't Screensavers Are Necessary?\n",
1615     "WELL ACTUALLY, screensavers aren't really nescessary anymore because ",
1616     "[S]", ".\n",
1617     "\n",
1618     "Please file complaints to @POTUS on Twitter.\n",
1619     "\n"
1620     "\n"
1621     "\n"
1622     "\n",
1623     "*GREETZ TO CRASH OVERRIDE AND ALSO JOEY\n",
1624   };
1625
1626   /* Make a 4:3 ratio box inside of the workspace */
1627   int box_width = bst->xgwa.width - (margin_size * 2);
1628   int box_height = bst->xgwa.height - bst->yoff - (margin_size * 2);
1629   int box_x = margin_size;
1630   int box_y = margin_size;
1631   if ((bst->xgwa.width / 4) * 3 > bst->xgwa.height) {
1632     /* Widescreen, make narrow bits */
1633     box_width = (bst->xgwa.height * 4 / 3) - (margin_size * 2);
1634     box_x = (bst->xgwa.width - box_width) / 2;
1635   } else {
1636     /* Narrowscreen, make wide bits */
1637     box_height = (bst->xgwa.width * 3 / 4) - (margin_size * 2);
1638     box_y = (bst->xgwa.height - bst->yoff - box_height) / 2;
1639   }
1640
1641   if (box_width < 750 && box_x == margin_size) {
1642     /* Not much width... */
1643     box_width = bst->xgwa.width;
1644     box_x = 0;
1645   }
1646
1647
1648   bst->xoff = bst->left_margin = bst->right_margin = 0;
1649
1650   if (!(random() % 8))
1651     return apple2ransomware (dpy, window);
1652
1653   /* Grab the desktop image */
1654   /* BSOD_IMG (bst); */
1655   bst->wrap_p = True;
1656
1657   /* Draw the main red window */
1658   BSOD_INVERT (bst);
1659   BSOD_RECT (bst, True, box_x, box_y, box_width, box_height);
1660
1661   if (pixmap) {
1662     bst->pixmap = pixmap;
1663     BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, box_x + logo_x, box_y + logo_y);
1664   }
1665
1666   /* Setup deadlines */
1667   strftime (stage1_deadline_str, sizeof(stage1_deadline_str),
1668             "%m/%d/%Y %H:%M:%S\n\n", localtime(&stage1_deadline));
1669   strftime (stage2_deadline_str, sizeof(stage1_deadline_str),
1670             "%m/%d/%Y %H:%M:%S\n\n", localtime(&stage2_deadline));
1671
1672   BSOD_INVERT (bst);
1673   /* Draw header pane */
1674   BSOD_FONT (bst, 0);
1675   BSOD_MOVETO (bst, box_x + right_pane_x, box_y + header_y + bst->fontA->ascent);
1676   BSOD_MARGINS (bst, box_x + right_pane_x, box_x);
1677   BSOD_COLOR (bst, fg, bg);
1678   BSOD_TEXT (bst, CENTER, header_quip);
1679
1680   /* Draw left-side timers */
1681   BSOD_MOVETO (bst, box_x, box_y + deadline_y);
1682   BSOD_MARGINS (bst, box_x, box_x + box_width - left_pane_width);
1683   BSOD_FONT (bst, 1);
1684
1685   BSOD_COLOR (bst, theader, bg);
1686   BSOD_TEXT (bst, CENTER, "Payment will be raised on\n");
1687   BSOD_COLOR (bst, fg, bg);
1688   BSOD_TEXT (bst, CENTER, stage1_deadline_str);
1689
1690   BSOD_TEXT (bst, CENTER, "Time Left\n");
1691   stage1_countdown_y = (line_height * 4) + box_y + deadline_y;
1692   BSOD_TEXT (bst, CENTER, "\n");
1693   BSOD_TEXT (bst, CENTER, "\n\n");
1694
1695   BSOD_COLOR (bst, theader, bg);
1696   BSOD_TEXT (bst, CENTER, "Your pixels will be lost on\n");
1697   BSOD_COLOR (bst, fg, bg);
1698   BSOD_TEXT (bst, CENTER, stage2_deadline_str);
1699
1700   BSOD_TEXT (bst, CENTER, "Time Left\n");
1701   stage2_countdown_y = (line_height * 9) + box_y + deadline_y;
1702   BSOD_TEXT (bst, CENTER, "\n");
1703
1704   /* Draw links */
1705   BSOD_FONT (bst, 1);
1706   BSOD_MOVETO (bst, box_x + links_x, box_y + box_height - links_height);
1707   BSOD_MARGINS (bst, box_x + links_x, box_x + box_width - left_pane_width);
1708   BSOD_COLOR (bst, link, bg);
1709
1710   if (box_height > 425) {
1711     /* Don't show this on small screens */
1712     BSOD_TEXT (bst, LEFT, "\n");
1713     BSOD_TEXT (bst, LEFT, "About ");
1714     BSOD_TEXT (bst, LEFT, currency);
1715     BSOD_TEXT (bst, LEFT, "\n\n"
1716                           "How to buy ");
1717     BSOD_TEXT (bst, LEFT, currency);
1718     BSOD_TEXT (bst, LEFT, "\n\n"
1719                           "Contact us\n");
1720   }
1721
1722   /* Ransom note text area */
1723   BSOD_COLOR (bst, bg2, fg2);
1724   BSOD_RECT (bst, True, box_x + right_pane_x, box_y + ransom_y,
1725              box_width - right_pane_x - 10,
1726              box_height - ransom_y - footer_height);
1727   BSOD_MOVETO (bst, box_x + right_pane_x + 5,
1728                box_y + ransom_y + (line_height * 1.1));
1729   BSOD_MARGINS (bst, box_x + right_pane_x + 5, box_x + 15);
1730   /* VERT_MARGINS are a bit high, to ensure we draw as much text as we can in
1731    * the box, even if the line is partially cut. We'll draw over this later.
1732    */
1733   BSOD_VERT_MARGINS (bst, box_y + ransom_y, box_y + (footer_height / 2));
1734   BSOD_INVERT (bst);
1735
1736   /* Write out the ransom note itself */
1737   BSOD_CROP (bst, True);
1738   for (i = 0; i < countof(lines); i++)
1739     {
1740       const char *s = lines[i];
1741       if (!strcmp(s, "[C]")) s = currency;
1742       else if  (!strcmp(s, "[Q]")) s = excuse_quip;
1743       else if  (!strcmp(s, "[S]")) s = screensaver_quip;
1744
1745       if (*s == '*')
1746         {
1747           s++;
1748           BSOD_FONT (bst, 2);
1749         }
1750       else
1751         BSOD_FONT (bst, 0);
1752
1753       BSOD_TEXT (bst, LEFT, s);
1754     }
1755   BSOD_CROP (bst, False);
1756   BSOD_FONT (bst, 0);
1757
1758   /* Draw over any overflowing ransom text. */
1759   BSOD_COLOR (bst, bg, fg);
1760   BSOD_RECT (bst, True, box_x + right_pane_x,
1761              box_y + box_height - footer_height,
1762              box_width - right_pane_x, footer_height);
1763
1764   /* Draw the footer */
1765   BSOD_COLOR (bst, theader, bg);
1766   BSOD_MOVETO (bst, box_x + right_pane_x,
1767                box_y + box_height - footer_height + line_height);
1768
1769   sprintf(buf, "Send $%.2f of %s to this address:\n", 101+frand(888), currency);
1770   BSOD_TEXT (bst, LEFT, buf);
1771   BSOD_COLOR (bst, fg2, bg2);
1772
1773   /* address, has some extra slashes in there because it's a fake address */
1774   for (i = 0; i < 40; i++) {
1775     const char *s =
1776       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123459789";
1777     buf[i] = s[random() % strlen(s)];
1778   }
1779   strncpy (buf, " //", 3);
1780   buf[10] = '/';
1781   buf[17] = '/';
1782   buf[24] = '/';
1783   strcpy (buf+33, " ");
1784   BSOD_TEXT (bst, LEFT, buf);
1785
1786   BSOD_COLOR (bst, fg, bg);
1787   BSOD_TEXT (bst, LEFT, "   ");
1788   BSOD_COLOR (bst, fg3, bg3);
1789   BSOD_TEXT (bst, LEFT, "  Copy  ");
1790   BSOD_COLOR (bst, fg, bg);
1791   BSOD_TEXT (bst, LEFT, "\n\n");
1792
1793   BSOD_COLOR (bst, fg3, bg3);
1794   BSOD_TEXT (bst, LEFT, "  Demogrify Screen  ");
1795   BSOD_COLOR (bst, fg, bg);
1796   BSOD_TEXT (bst, LEFT, "            ");
1797   BSOD_COLOR (bst, fg3, bg3);
1798   BSOD_TEXT (bst, LEFT, "  Check Payment  ");
1799
1800
1801   /* Draw countdown timers */
1802   BSOD_COLOR (bst, fg, bg);
1803   BSOD_FONT (bst, 0);
1804   do {
1805     /* First timer */
1806     BSOD_MOVETO (bst, box_x, stage1_countdown_y);
1807     BSOD_MARGINS (bst, box_x, box_x + box_width - left_pane_width);
1808
1809     countdown_r = stage1_deadline - now;
1810     countdown_s = countdown_r % 60;
1811     countdown_m = (countdown_r / 60) % 60;
1812     countdown_h = (countdown_r / 3600) % 24;
1813     countdown_d = (countdown_r / 86400);
1814
1815     sprintf (countdown_str, "%02d:%02d:%02d:%02d\n",
1816              countdown_d, countdown_h, countdown_m, countdown_s);
1817
1818     BSOD_TEXT (bst, CENTER, countdown_str);
1819
1820     /* Second timer */
1821     BSOD_MOVETO (bst, box_x, stage2_countdown_y);
1822
1823     countdown_r = stage2_deadline - now;
1824     countdown_s = countdown_r % 60;
1825     countdown_m = (countdown_r / 60) % 60;
1826     countdown_h = (countdown_r / 3600) % 24;
1827     countdown_d = (countdown_r / 86400);
1828
1829     sprintf (countdown_str, "%02d:%02d:%02d:%02d\n",
1830              countdown_d, countdown_h, countdown_m, countdown_s);
1831
1832     BSOD_TEXT (bst, CENTER, countdown_str);
1833
1834     BSOD_PAUSE (bst, 1000000);
1835     now++;
1836
1837     /* While the "correct" thing to do is create enough of a script to fill the
1838      * stage2_deadline, this would be 7 days of "frames", which is quite a bit
1839      * of memory. Instead, only fill the buffer with 1 hour of frames, which is
1840      * enough to make the point before xscreensaver cycles us.
1841      */
1842   } while (stage1_deadline - now > 3600);
1843
1844   XClearWindow (dpy, window);
1845   return bst;
1846 }
1847
1848
1849 /* As seen in Portal 2.  By jwz.
1850  */
1851 static struct bsod_state *
1852 glados (Display *dpy, Window window)
1853 {
1854   struct bsod_state *bst = make_bsod_state (dpy, window, "glaDOS", "GlaDOS");
1855   const char * panicstr[] = {
1856     "\n",
1857     "MOLTEN CORE WARNING\n",
1858     "\n",
1859     "An operator error exception has occurred at FISSREAC0020093:09\n",
1860     "FISSREAC0020077:14 FISSREAC0020023:17 FISSREAC0020088:22\n",
1861     "neutron multiplication rate at spikevalue 99999999\n",
1862     "\n",
1863     "* Press any key to vent radiological emissions into atmosphere.\n",
1864     "* Consult reactor core manual for instructions on proper reactor core\n",
1865     "maintenance and repair.\n",
1866     "\n",
1867     "Press any key to continue\n",
1868   };
1869
1870   int i;
1871
1872   bst->xoff = bst->left_margin = bst->right_margin = 0;
1873
1874   bst->y = ((bst->xgwa.height - bst->yoff -
1875              ((bst->font->ascent + bst->font->descent) * countof(panicstr)))
1876             / 2);
1877
1878   BSOD_MOVETO (bst, 0, bst->y);
1879   BSOD_INVERT (bst);
1880   BSOD_TEXT   (bst,  CENTER, "OPERATOR ERROR\n");
1881   BSOD_INVERT (bst);
1882   for (i = 0; i < countof(panicstr); i++)
1883     BSOD_TEXT (bst, CENTER, panicstr[i]);
1884   BSOD_PAUSE (bst, 1000000);
1885   BSOD_INVERT (bst);
1886   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
1887   BSOD_INVERT (bst);
1888   BSOD_PAUSE (bst, 250000);
1889   BSOD_RESET (bst);
1890
1891   XClearWindow (dpy, window);
1892   return bst;
1893 }
1894
1895
1896
1897 /* SCO OpenServer 5 panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
1898  */
1899 static struct bsod_state *
1900 sco (Display *dpy, Window window)
1901 {
1902   struct bsod_state *bst = make_bsod_state (dpy, window, "sco", "SCO");
1903
1904   BSOD_TEXT (bst, LEFT,
1905      "Unexpected trap in kernel mode:\n"
1906      "\n"
1907      "cr0 0x80010013     cr2  0x00000014     cr3 0x00000000  tlb  0x00000000\n"
1908      "ss  0x00071054    uesp  0x00012055     efl 0x00080888  ipl  0x00000005\n"
1909      "cs  0x00092585     eip  0x00544a4b     err 0x004d4a47  trap 0x0000000E\n"
1910      "eax 0x0045474b     ecx  0x0042544b     edx 0x57687920  ebx  0x61726520\n"
1911      "esp 0x796f7520     ebp  0x72656164     esi 0x696e6720  edi  0x74686973\n"
1912      "ds  0x3f000000     es   0x43494c48     fs  0x43525343  gs   0x4f4d4b53\n"
1913      "\n"
1914      "PANIC: k_trap - kernel mode trap type 0x0000000E\n"
1915      "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n"
1916     );
1917   BSOD_CHAR_DELAY (bst, 100000);
1918   BSOD_TEXT (bst, LEFT,
1919     "................................................................."
1920     "..............\n"
1921     );
1922   BSOD_CHAR_DELAY (bst, 0);
1923   BSOD_TEXT (bst, LEFT,
1924      "5023 pages dumped\n"
1925      "\n"
1926      "\n"
1927      );
1928   BSOD_PAUSE (bst, 2000000);
1929   BSOD_TEXT (bst, LEFT,
1930      "**   Safe to Power Off   **\n"
1931      "           - or -\n"
1932      "** Press Any Key to Reboot **\n"
1933     );
1934
1935   bst->y = ((bst->xgwa.height - bst->yoff -
1936              ((bst->font->ascent + bst->font->descent) * 18)));
1937
1938   XClearWindow (dpy, window);
1939   return bst;
1940 }
1941
1942
1943 /* Linux (sparc) panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
1944  */
1945 static struct bsod_state *
1946 sparc_linux (Display *dpy, Window window)
1947 {
1948   struct bsod_state *bst = make_bsod_state (dpy, window,
1949                                             "sparclinux", "SparcLinux");
1950   bst->scroll_p = True;
1951   bst->y = bst->xgwa.height - bst->yoff
1952     - bst->font->ascent - bst->font->descent;
1953
1954   BSOD_TEXT (bst, LEFT,
1955         "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
1956         "Unable to handle kernel paging request at virtual address f0d4a000\n"
1957         "tsk->mm->context = 00000014\n"
1958         "tsk->mm->pgd = f26b0000\n"
1959         "              \\|/ ____ \\|/\n"
1960         "              \"@'/ ,. \\`@\"\n"
1961         "              /_| \\__/ |_\\\n"
1962         "                 \\__U_/\n"
1963         "gawk(22827): Oops\n"
1964         "PSR: 044010c1 PC: f001c2cc NPC: f001c2d0 Y: 00000000\n"
1965         "g0: 00001000 g1: fffffff7 g2: 04401086 g3: 0001eaa0\n"
1966         "g4: 000207dc g5: f0130400 g6: f0d4a018 g7: 00000001\n"
1967         "o0: 00000000 o1: f0d4a298 o2: 00000040 o3: f1380718\n"
1968         "o4: f1380718 o5: 00000200 sp: f1b13f08 ret_pc: f001c2a0\n"
1969         "l0: efffd880 l1: 00000001 l2: f0d4a230 l3: 00000014\n"
1970         "l4: 0000ffff l5: f0131550 l6: f012c000 l7: f0130400\n"
1971         "i0: f1b13fb0 i1: 00000001 i2: 00000002 i3: 0007c000\n"
1972         "i4: f01457c0 i5: 00000004 i6: f1b13f70 i7: f0015360\n"
1973         "Instruction DUMP:\n"
1974     );
1975
1976   XClearWindow (dpy, window);
1977   return bst;
1978 }
1979
1980
1981 /* BSD Panic by greywolf@starwolf.com - modeled after the Linux panic above.
1982    By Grey Wolf <greywolf@siteROCK.com>
1983  */
1984 static struct bsod_state *
1985 bsd (Display *dpy, Window window)
1986 {
1987   struct bsod_state *bst = make_bsod_state (dpy, window, "bsd", "BSD");
1988
1989   const char * const panicstr[] = {
1990     "panic: ifree: freeing free inode\n",
1991     "panic: blkfree: freeing free block\n",
1992     "panic: improbability coefficient below zero\n",
1993     "panic: cgsixmmap\n",
1994     "panic: crazy interrupts\n",
1995     "panic: nmi\n",
1996     "panic: attempted windows install\n",
1997     "panic: don't\n",
1998     "panic: free inode isn't\n",
1999     "panic: cpu_fork: curproc\n",
2000     "panic: malloc: out of space in kmem_map\n",
2001     "panic: vogon starship detected\n",
2002     "panic: teleport chamber: out of order\n",
2003     "panic: Brain fried - core dumped\n"
2004    };
2005   int i, n, b;
2006   char syncing[80], bbuf[5];
2007
2008   for (i = 0; i < sizeof(syncing); i++)
2009     syncing[i] = 0;
2010
2011   i = (random() % (sizeof(panicstr) / sizeof(*panicstr)));
2012   BSOD_TEXT (bst, LEFT, panicstr[i]);
2013   BSOD_TEXT (bst, LEFT, "Syncing disks: ");
2014
2015   b = (random() % 40);
2016   for (n = 0; (n < 20) && (b > 0); n++)
2017     {
2018       if (i)
2019         {
2020           i = (random() & 0x7);
2021           b -= (random() & 0xff) % 20;
2022           if (b < 0)
2023             b = 0;
2024         }
2025       sprintf (bbuf, "%d ", b);
2026       BSOD_TEXT (bst, LEFT, bbuf);
2027       BSOD_PAUSE (bst, 1000000);
2028     }
2029
2030   BSOD_TEXT (bst, LEFT, "\n");
2031   BSOD_TEXT (bst, LEFT, (b ? "damn!" : "sunk!"));
2032   BSOD_TEXT (bst, LEFT, "\nRebooting\n");
2033
2034   bst->y = ((bst->xgwa.height - bst->yoff -
2035              ((bst->font->ascent + bst->font->descent) * 4)));
2036
2037   XClearWindow (dpy, window);
2038   return bst;
2039 }
2040
2041
2042 static struct bsod_state *
2043 amiga (Display *dpy, Window window)
2044 {
2045   struct bsod_state *bst = make_bsod_state (dpy, window, "amiga", "Amiga");
2046
2047   Pixmap pixmap = 0;
2048   int pix_w = 0, pix_h = 0;
2049   int height;
2050   int lw = 10;
2051
2052   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
2053                                           "amiga.background2",
2054                                           "Amiga.Background");
2055
2056   bst->yoff = 0;
2057   bst->top_margin = bst->bottom_margin = 0;
2058
2059 # ifdef DO_XPM
2060   pixmap = xpm_data_to_pixmap (dpy, window, (char **) amiga_hand,
2061                                &pix_w, &pix_h, 0);
2062 # endif /* DO_XPM */
2063
2064   if (pixmap &&
2065       MIN (bst->xgwa.width, bst->xgwa.height) > 600) /* scale up the bitmap */
2066     {
2067       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
2068                               pixmap, pix_w, pix_h);
2069       pix_w *= 2;
2070       pix_h *= 2;
2071       lw *= 2;
2072     }
2073
2074   XSetLineAttributes (dpy, bst->gc, lw, LineSolid, CapButt, JoinMiter);
2075
2076   height = (bst->font->ascent + bst->font->descent) * 6;
2077
2078   BSOD_PAUSE (bst, 2000000);
2079   BSOD_COPY (bst, 0, 0, bst->xgwa.width, bst->xgwa.height - height, 0, height);
2080
2081   BSOD_INVERT (bst);
2082   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, height);
2083   BSOD_INVERT (bst);
2084   BSOD_TEXT (bst, CENTER,
2085              "\n"
2086              "Software failure.  Press left mouse button to continue.\n"
2087              "Guru Meditation #00000003.00C01570"
2088              );
2089   BSOD_RECT (bst, False, lw/2, lw/2, bst->xgwa.width - lw, height);
2090   BSOD_PAUSE (bst, 1000000);
2091   BSOD_INVERT (bst);
2092   BSOD_LOOP (bst, -3);
2093
2094   XSetWindowBackground (dpy, window, bg2);
2095   XClearWindow (dpy, window);
2096   XSetWindowBackground (dpy, window, bst->bg);
2097
2098   if (pixmap)
2099     {
2100       int x = (bst->xgwa.width - pix_w) / 2;
2101       int y = ((bst->xgwa.height - pix_h) / 2);
2102       XCopyArea (dpy, pixmap, bst->window, bst->gc, 0, 0, pix_w, pix_h, x, y);
2103     }
2104
2105   bst->y += lw;
2106
2107   return bst;
2108 }
2109
2110
2111
2112 /* Atari ST, by Marcus Herbert <rhoenie@nobiscum.de>
2113    Marcus had this to say:
2114
2115         Though I still have my Atari somewhere, I hardly remember
2116         the meaning of the bombs. I think 9 bombs was "bus error" or
2117         something like that.  And you often had a few bombs displayed
2118         quickly and then the next few ones coming up step by step.
2119         Perhaps somebody else can tell you more about it..  its just
2120         a quick hack :-}
2121  */
2122 static struct bsod_state *
2123 atari (Display *dpy, Window window)
2124 {
2125   struct bsod_state *bst = make_bsod_state (dpy, window, "atari", "Atari");
2126
2127   Pixmap pixmap = 0;
2128   int pix_w = atari_width;
2129   int pix_h = atari_height;
2130   int offset;
2131   int i, x, y;
2132
2133   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) atari_bits,
2134                                         pix_w, pix_h,
2135                                         bst->fg, bst->bg, bst->xgwa.depth);
2136   pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
2137                           pixmap, pix_w, pix_h);
2138   pix_w *= 2;
2139   pix_h *= 2;
2140
2141   offset = pix_w;
2142   x = 0;
2143   y = bst->xgwa.height/2;
2144   if (y < 0) y = 0;
2145
2146   for (i = 1; i< 7; i++)
2147     BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y);
2148
2149   for (; i< 10; i++)
2150     {
2151       BSOD_PAUSE (bst, 1000000);
2152       BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y);
2153     }
2154
2155   XClearWindow (dpy, window);
2156   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
2157   XFreePixmap (dpy, pixmap);
2158
2159   return bst;
2160 }
2161
2162
2163 static struct bsod_state *
2164 mac (Display *dpy, Window window)
2165 {
2166   struct bsod_state *bst = make_bsod_state (dpy, window, "mac", "Mac");
2167
2168   Pixmap pixmap = 0;
2169   int pix_w = mac_width;
2170   int pix_h = mac_height;
2171   int offset = mac_height * 4;
2172   int i;
2173
2174   const char *string = ("0 0 0 0 0 0 0 F\n"
2175                         "0 0 0 0 0 0 0 3");
2176
2177   bst->xoff = bst->left_margin = bst->right_margin = 0;
2178
2179   pixmap = XCreatePixmapFromBitmapData(dpy, window, (char *) mac_bits,
2180                                        mac_width, mac_height,
2181                                        bst->fg, bst->bg, bst->xgwa.depth);
2182
2183   for (i = 0; i < 2; i++)
2184     {
2185       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
2186                               pixmap, pix_w, pix_h);
2187       pix_w *= 2; pix_h *= 2;
2188     }
2189
2190   bst->x = (bst->xgwa.width - pix_w) / 2;
2191   bst->y = (((bst->xgwa.height + offset) / 2) -
2192             pix_h -
2193             (bst->font->ascent + bst->font->descent) * 2);
2194   if (bst->y < 0) bst->y = 0;
2195
2196   XClearWindow (dpy, window);
2197   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, bst->x, bst->y);
2198   XFreePixmap (dpy, pixmap);
2199
2200   bst->y += offset + bst->font->ascent + bst->font->descent;
2201   BSOD_TEXT (bst, CENTER, string);
2202
2203   return bst;
2204 }
2205
2206
2207 static struct bsod_state *
2208 macsbug (Display *dpy, Window window)
2209 {
2210   struct bsod_state *bst = make_bsod_state (dpy, window, "macsbug", "MacsBug");
2211
2212   __extension__
2213   const char *left = ("    SP     \n"
2214                       " 04EB0A58  \n"
2215                       "58 00010000\n"
2216                       "5C 00010000\n"
2217                       "   ........\n"
2218                       "60 00000000\n"
2219                       "64 000004EB\n"
2220                       "   ........\n"
2221                       "68 0000027F\n"
2222                       "6C 2D980035\n"
2223                       "   ....-..5\n"
2224                       "70 00000054\n"
2225                       "74 0173003E\n"
2226                       "   ...T.s.>\n"
2227                       "78 04EBDA76\n"
2228                       "7C 04EBDA8E\n"
2229                       "   .S.L.a.U\n"
2230                       "80 00000000\n"
2231                       "84 000004EB\n"
2232                       "   ........\n"
2233                       "88 00010000\n"
2234                       "8C 00010000\n"
2235                       "   ...{3..S\n"
2236                       "\n"
2237                       "\n"
2238                       " CurApName \n"
2239                       "  Finder   \n"
2240                       "\n"
2241                       " 32-bit VM \n"
2242                       "SR Smxnzvc0\n"
2243                       "D0 04EC0062\n"
2244                       "D1 00000053\n"
2245                       "D2 FFFF0100\n"
2246                       "D3 00010000\n"
2247                       "D4 00010000\n"
2248                       "D5 04EBDA76\n"
2249                       "D6 04EBDA8E\n"
2250                       "D7 00000001\n"
2251                       "\n"
2252                       "A0 04EBDA76\n"
2253                       "A1 04EBDA8E\n"
2254                       "A2 A0A00060\n"
2255                       "A3 027F2D98\n"
2256                       "A4 027F2E58\n"
2257                       "A5 04EC04F0\n"
2258                       "A6 04EB0A86\n"
2259                       "A7 04EB0A58");
2260   const char *bottom = ("  _A09D\n"
2261                         "     +00884    40843714     #$0700,SR         "
2262                         "                  ; A973        | A973\n"
2263                         "     +00886    40843765     *+$0400           "
2264                         "                                | 4A1F\n"
2265                         "     +00888    40843718     $0004(A7),([0,A7[)"
2266                         "                  ; 04E8D0AE    | 66B8");
2267   __extension__
2268   const char * body = ("PowerPC unmapped memory exception at 003AFDAC "
2269                                                 "BowelsOfTheMemoryMgr+04F9C\n"
2270                       " Calling chain using A6/R1 links\n"
2271                       "  Back chain  ISA  Caller\n"
2272                       "  00000000    PPC  28C5353C  __start+00054\n"
2273                       "  24DB03C0    PPC  28B9258C  main+0039C\n"
2274                       "  24DB0350    PPC  28B9210C  MainEvent+00494\n"
2275                       "  24DB02B0    PPC  28B91B40  HandleEvent+00278\n"
2276                       "  24DB0250    PPC  28B83DAC  DoAppleEvent+00020\n"
2277                       "  24DB0210    PPC  FFD3E5D0  "
2278                                                 "AEProcessAppleEvent+00020\n"
2279                       "  24DB0132    68K  00589468\n"
2280                       "  24DAFF8C    68K  00589582\n"
2281                       "  24DAFF26    68K  00588F70\n"
2282                       "  24DAFEB3    PPC  00307098  "
2283                                                 "EmToNatEndMoveParams+00014\n"
2284                       "  24DAFE40    PPC  28B9D0B0  DoScript+001C4\n"
2285                       "  24DAFDD0    PPC  28B9C35C  RunScript+00390\n"
2286                       "  24DAFC60    PPC  28BA36D4  run_perl+000E0\n"
2287                       "  24DAFC10    PPC  28BC2904  perl_run+002CC\n"
2288                       "  24DAFA80    PPC  28C18490  Perl_runops+00068\n"
2289                       "  24DAFA30    PPC  28BE6CC0  Perl_pp_backtick+000FC\n"
2290                       "  24DAF9D0    PPC  28BA48B8  Perl_my_popen+00158\n"
2291                       "  24DAF980    PPC  28C5395C  sfclose+00378\n"
2292                       "  24DAF930    PPC  28BA568C  free+0000C\n"
2293                       "  24DAF8F0    PPC  28BA6254  pool_free+001D0\n"
2294                       "  24DAF8A0    PPC  FFD48F14  DisposePtr+00028\n"
2295                       "  24DAF7C9    PPC  00307098  "
2296                                                 "EmToNatEndMoveParams+00014\n"
2297                       "  24DAF780    PPC  003AA180  __DisposePtr+00010");
2298
2299   const char *s;
2300   int body_lines = 1;
2301
2302   int char_width, line_height;
2303   int col_right, row_top, row_bottom, page_right, page_bottom, body_top;
2304   int xoff, yoff;
2305
2306   unsigned long fg = bst->fg;
2307   unsigned long bg = bst->bg;
2308   unsigned long bc = get_pixel_resource (dpy, bst->xgwa.colormap,
2309                                          "macsbug.borderColor",
2310                                          "MacsBug.BorderColor");
2311
2312   bst->xoff = bst->left_margin = bst->right_margin = 0;
2313
2314   for (s = body; *s; s++) if (*s == '\n') body_lines++;
2315
2316   char_width = (bst->font->per_char
2317                 ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
2318                 : bst->font->min_bounds.width);
2319   line_height = bst->font->ascent + bst->font->descent;
2320
2321   col_right   = char_width  * 12;  /* number of columns in `left' */
2322   page_bottom = line_height * 47;  /* number of lines in `left'   */
2323
2324   if (page_bottom > bst->xgwa.height - bst->yoff)
2325     page_bottom = bst->xgwa.height - bst->yoff;
2326
2327   row_bottom = page_bottom - line_height;
2328   row_top    = row_bottom - (line_height * 4);
2329   page_right = col_right + (char_width * 88);
2330   body_top   = row_top - (line_height * body_lines);
2331
2332   page_bottom += 2;
2333   row_bottom += 2;
2334   body_top -= 4;
2335
2336   if (body_top > 4)
2337     body_top = 4;
2338
2339   xoff = (bst->xgwa.width  - page_right)  / 2;
2340   yoff = (bst->xgwa.height - page_bottom) / 2;
2341
2342   if (xoff < 0) xoff = 0;
2343   if (yoff < 0) yoff = 0;
2344
2345   BSOD_MARGINS (bst, xoff, yoff);
2346
2347   BSOD_COLOR (bst, bc, bg);
2348   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
2349   BSOD_COLOR (bst, bg, bg);
2350   BSOD_RECT (bst, True, xoff-2, yoff, page_right+4, page_bottom);
2351   BSOD_COLOR (bst, fg, bg);
2352
2353   BSOD_MOVETO (bst, xoff, yoff + line_height);
2354   BSOD_TEXT (bst, LEFT, left);
2355   BSOD_MOVETO (bst, xoff+col_right, yoff + row_top + line_height);
2356   BSOD_TEXT (bst, LEFT, bottom);
2357
2358   BSOD_RECT (bst, True, xoff + col_right, yoff, 2, page_bottom);
2359   BSOD_RECT (bst, True, xoff + col_right, yoff + row_top,
2360              page_right - col_right, 1);
2361   BSOD_RECT (bst, True, xoff + col_right, yoff + row_bottom,
2362              page_right - col_right, 1);
2363   BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom);
2364
2365   BSOD_LINE_DELAY (bst, 500);
2366   BSOD_MOVETO (bst,
2367                xoff + col_right + char_width,
2368                yoff + body_top + line_height);
2369   BSOD_MARGINS (bst, xoff + col_right + char_width, yoff);
2370   BSOD_TEXT (bst, LEFT, body);
2371
2372   BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom); /* again */
2373
2374   BSOD_RECT (bst, False,
2375              xoff + col_right + (char_width/2)+2,
2376              yoff + row_bottom + 2,
2377              0,
2378              page_bottom - row_bottom - 4);
2379
2380   BSOD_PAUSE (bst, 666666);
2381   BSOD_INVERT (bst);
2382   BSOD_LOOP (bst, -3);
2383
2384   XClearWindow (dpy, window);
2385   return bst;
2386 }
2387
2388
2389 static struct bsod_state *
2390 mac1 (Display *dpy, Window window)
2391 {
2392   struct bsod_state *bst = make_bsod_state (dpy, window, "mac1", "Mac1");
2393
2394   Pixmap pixmap = 0;
2395   int pix_w = macbomb_width;
2396   int pix_h = macbomb_height;
2397   int x, y;
2398
2399   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) macbomb_bits,
2400                                         macbomb_width, macbomb_height,
2401                                         bst->fg, bst->bg, bst->xgwa.depth);
2402
2403   if (pixmap && 
2404       pix_w < bst->xgwa.width / 2 &&
2405       pix_h < bst->xgwa.height / 2)
2406     {
2407       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual,
2408                               bst->xgwa.depth, pixmap, pix_w, pix_h);
2409       pix_w *= 2;
2410       pix_h *= 2;
2411     }
2412
2413   x = (bst->xgwa.width - pix_w) / 2;
2414   y = (bst->xgwa.height - pix_h) / 2;
2415   if (y < 0) y = 0;
2416
2417   XClearWindow (dpy, window);
2418   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
2419
2420   return bst;
2421 }
2422
2423
2424 /* This is what kernel panics looked like on MacOS X 10.0 through 10.1.5.
2425    In later releases, it's a graphic of a power button with text in
2426    English, French, German, and Japanese overlayed transparently.
2427  */
2428 static struct bsod_state *
2429 macx_10_0 (Display *dpy, Window window)
2430 {
2431   struct bsod_state *bst = make_bsod_state (dpy, window, "macx", "MacX");
2432
2433   XClearWindow (dpy, window);
2434   XSetForeground (dpy, bst->gc,
2435                   get_pixel_resource (dpy, bst->xgwa.colormap,
2436                                       "macx.textForeground",
2437                                       "MacX.TextForeground"));
2438   XSetBackground (dpy, bst->gc,
2439                   get_pixel_resource (dpy, bst->xgwa.colormap,
2440                                       "macx.textBackground",
2441                                       "MacX.TextBackground"));
2442
2443 # ifdef DO_XPM
2444   {
2445     Pixmap pixmap = 0;
2446     Pixmap mask = 0;
2447     int x, y, pix_w, pix_h;
2448     pixmap = xpm_data_to_pixmap (dpy, window, (char **) happy_mac,
2449                                  &pix_w, &pix_h, &mask);
2450
2451 # ifdef HAVE_MOBILE
2452     if (pixmap)
2453       {
2454         pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual,
2455                                 bst->xgwa.depth, pixmap, pix_w, pix_h);
2456         mask = double_pixmap (dpy, bst->gc, bst->xgwa.visual,
2457                               1, mask, pix_w, pix_h);
2458         pix_w *= 2;
2459         pix_h *= 2;
2460       }
2461 # endif
2462
2463     x = (bst->xgwa.width - pix_w) / 2;
2464     y = (bst->xgwa.height - pix_h) / 2;
2465     if (y < 0) y = 0;
2466     XSetClipMask (dpy, bst->gc, mask);
2467     XSetClipOrigin (dpy, bst->gc, x, y);
2468     XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
2469     XSetClipMask (dpy, bst->gc, None);
2470     XFreePixmap (dpy, pixmap);
2471   }
2472 #endif /* DO_XPM */
2473
2474   bst->left_margin = 0;
2475   bst->right_margin = 0;
2476   bst->y = bst->font->ascent;
2477   bst->macx_eol_kludge = True;
2478   bst->wrap_p = True;
2479
2480   BSOD_PAUSE (bst, 3000000);
2481   BSOD_TEXT (bst, LEFT,
2482     "panic(cpu 0): Unable to find driver for this platform: "
2483     "\"PowerMac 3,5\".\n"
2484     "\n"
2485     "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
2486     "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
2487     "\n"
2488     "\n"
2489     "\n"
2490     "No debugger configured - dumping debug information\n"
2491     "\n"
2492     "version string : Darwin Kernel Version 1.3:\n"
2493     "Thu Mar  1 06:56:40 PST 2001; root:xnu/xnu-123.5.obj~1/RELEASE_PPC\n"
2494     "\n"
2495     "\n"
2496     "\n"
2497     "\n"
2498     "DBAT0: 00000000 00000000\n"
2499     "DBAT1: 00000000 00000000\n"
2500     "DBAT2: 80001FFE 8000003A\n"
2501     "DBAT3: 90001FFE 9000003A\n"
2502     "MSR=00001030\n"
2503     "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
2504     "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
2505     "\n"
2506     "panic: We are hanging here...\n");
2507
2508   return bst;
2509 }
2510
2511
2512 # ifdef DO_XPM
2513 static struct bsod_state *
2514 macx_10_2 (Display *dpy, Window window, Bool v10_3_p)
2515 {
2516   struct bsod_state *bst = make_bsod_state (dpy, window, "macx", "MacX");
2517
2518   Pixmap pixmap = 0;
2519   int pix_w = 0, pix_h = 0;
2520   int x, y;
2521
2522   pixmap = xpm_data_to_pixmap (dpy, window,
2523                                (char **) (v10_3_p ? osx_10_3 : osx_10_2),
2524                                &pix_w, &pix_h, 0);
2525   if (! pixmap) abort();
2526
2527 #if 0
2528   if (bst->xgwa.height > 600)   /* scale up the bitmap */
2529     {
2530       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
2531                               pixmap, pix_w, pix_h);
2532       if (! pixmap) abort();
2533       pix_w *= 2;
2534       pix_h *= 2;
2535     }
2536 #endif
2537
2538   BSOD_IMG (bst);
2539   BSOD_PAUSE (bst, 2000000);
2540
2541   bst->pixmap = pixmap;
2542
2543   x = (bst->xgwa.width - pix_w) / 2;
2544   y = ((bst->xgwa.height - pix_h) / 2);
2545   BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, x, y);
2546
2547   return bst;
2548 }
2549 # endif /* DO_XPM */
2550
2551
2552 /* 2006 Mac Mini with MacOS 10.6 failing with a bad boot drive. By jwz.
2553  */
2554 static struct bsod_state *
2555 mac_diskfail (Display *dpy, Window window)
2556 {
2557   struct bsod_state *bst = make_bsod_state (dpy, window, "macdisk", "Mac");
2558   int cw = (bst->font->per_char
2559             ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
2560             : bst->font->min_bounds.width);
2561   int h = bst->font->ascent + bst->font->descent;
2562   int L = (bst->xgwa.width - (cw * 80)) / 2;
2563   int T = (bst->xgwa.height - (h  * 10)) / 2;
2564
2565   unsigned long fg = bst->fg;
2566   unsigned long bg = bst->bg;
2567   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
2568                                           "macx.background",
2569                                           "Mac.Background");
2570   if (L < 0) L = 0;
2571   if (T < 0) T = 0;
2572
2573   bst->wrap_p = True;
2574   bst->scroll_p = True;
2575
2576   BSOD_COLOR(bst, bg2, bg);
2577   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
2578   BSOD_PAUSE (bst, 3000000);
2579
2580   BSOD_COLOR(bst, bg, fg);
2581   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
2582   BSOD_COLOR(bst, fg, bg);
2583
2584   BSOD_MARGINS (bst, L, L);
2585   BSOD_MOVETO (bst, L, T);
2586
2587   BSOD_TEXT (bst, LEFT,
2588              "efiboot loaded from device: Acpi(PNP0A03,0)/Pci*1F|2)/Ata"
2589              "(Primary,Slave)/HD(Part\n"
2590              "2,Sig8997E427-064E-4FE7-8CB9-F27A784B232C)\n"
2591              "boot file path: \\System\\Library\\CoreServices\\boot.efi\n"
2592              ".Loading kernel cache file 'System\\Library\\Caches\\"
2593              "com.apple.kext.caches\\Startup\\\n"
2594              "kernelcache_i386.2A14EC2C'\n"
2595              "Loading 'mach_kernel'...\n"
2596              );
2597   BSOD_CHAR_DELAY (bst, 7000);
2598   BSOD_TEXT (bst, LEFT,
2599              ".....................\n"
2600              );
2601   BSOD_CHAR_DELAY (bst, 0);
2602   BSOD_TEXT (bst, LEFT,
2603              "root device uuid is 'B62181B4-6755-3C27-BFA1-49A0E053DBD6\n"
2604              "Loading drivers...\n"
2605              "Loading System\\Library\\Caches\\com.apple.kext.caches\\"
2606              "Startup\\Extensions.mkext....\n"
2607              );
2608   BSOD_CHAR_DELAY (bst, 7000);
2609   BSOD_TEXT (bst, LEFT,
2610              "..............................................................."
2611              ".................\n"
2612              "..............................................................."
2613              ".................\n"
2614              "..............\n"
2615              );
2616   BSOD_INVERT (bst);
2617   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
2618   BSOD_INVERT (bst);
2619
2620   BSOD_MARGINS (bst, 0, 0);
2621   BSOD_MOVETO (bst, 0, h);
2622
2623   BSOD_CHAR_DELAY (bst, 0);
2624   BSOD_LINE_DELAY (bst, 5000);
2625   BSOD_TEXT (bst, LEFT,
2626              "npvhash=4095\n"
2627              "PRE enabled\n"
2628              "Darwin Kernel Version 10.8.9: Tue Jun  7 16:33:36 PDT 2011;"
2629              " root:xnu-1504.15.3~1/RELEASE_I386\n"
2630              "vm_page_bootstrap: 508036 free pages and 16252 wired pages\n"
2631              "standard timeslicing quantum is 10000 us\n"
2632              "mig_table_max_displ = 73\n"
2633              "AppleACPICPU: ProcessorId=0 LocalApicId=0 Enabled\n"
2634              "AppleACPICPU: ProcessorId=1 LocalApicId=1 Enabled\n"
2635              "calling npo_policy_init for Quarantine\n"
2636              "Security policy loaded: Quaantine policy (Quarantine)\n"
2637              "calling npo_policy_init for Sandbox\n"
2638              "Security policy loaded: Seatbelt sandbox policy (Sandbox)\n"
2639              "calling npo_policy_init for TMSafetyNet\n"
2640              "Security policy loaded: Safety net for Time Machine "
2641              "(TMSafetyNet)\n"
2642              "Copyright (c) 1982, 1986, 1989, 1991, 1993\n"
2643              "The Regents of the University of California. All rights "
2644              "reserved.\n"
2645              "\n"
2646              "MAC Framework successfully initialized\n"
2647              "using 10485 buffer headers and 4096 cluster IO buffer headers\n"
2648              "IOAPIC: Version 0x20 Vectors 64:87\n"
2649              "ACPI: System State [S0 S3 S4 S5] (S3)\n"
2650              "PFM64 0x10000000, 0xf0000000\n"
2651              "[ PCI configuration begin ]\n"
2652              "PCI configuration changed (bridge=1 device=1 cardbus=0)\n"
2653              "[ PCI configuration end, bridges 4 devices 17 ]\n"
2654              "nbinit: done (64 MB memory set for nbuf pool)\n"
2655              "rooting via boot-uuid from /chosen: "
2656              "B62181B4-6755-3C27-BFA1-49A0E053DBD6\n"
2657              "Waiting on <dict ID=\"0\"><key>IOProviderClass</key>"
2658              "<string ID=\"1\">IOResources</string><key>IOResourceMatch</key>"
2659              "<string ID=\"2\">boot-uuid-nedia</string></dict>\n"
2660              "com.apple.AppleFSCCompressionTypeZlib kmod start\n"
2661              "com.apple.AppleFSCCompressionTypeZlib kmod succeeded\n"
2662              "AppleIntelCPUPowerManagementClient: ready\n"
2663              "FireWire (OHCI) Lucent ID 5811  built-in now active, GUID "
2664              "0019e3fffe97f8b4; max speed s400.\n"
2665              "Got boot device = IOService:/AppleACPIPlatformExpert/PCI000/"
2666              "AppleACPIPCI/SATA@1F,2/AppleAHCI/PRI202/IOAHCIDevice@0/"
2667              "AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/"
2668              "IOBlockStorageDriver/ST96812AS Media/IOGUIDPartitionScheme/"
2669              "Customer02\n"
2670              );
2671   BSOD_PAUSE (bst, 1000000);
2672   BSOD_TEXT (bst, LEFT,
2673              "BSD root: Disk0s, major 14, minor 2\n"
2674              "[Bluetooth::CSRHIDTransition] switchtoHCIMode (legacy)\n"
2675              "[Bluetooth::CSRHIDTransition] transition complete.\n"
2676              "CSRUSBBluetoothHCIController::setupHardware super returned 0\n"
2677              );
2678   BSOD_PAUSE (bst, 3000000);
2679   BSOD_TEXT (bst, LEFT,
2680              "disk0s2: I/O error.\n"
2681              "0 [Level 3] [ReadUID 0] [Facility com.apple.system.fs] "
2682              "[ErrType IO] [ErrNo 5] [IOType Read] [PBlkNum 48424] "
2683              "[LBlkNum 1362] [FSLogMsgID 2009724291] [FSLogMsgOrder First]\n"
2684              "0 [Level 3] [ReadUID 0] [Facility com.apple.system.fs] "
2685              "[DevNode root_device] [MountPt /] [FSLogMsgID 2009724291] "
2686              "[FSLogMsgOrder Last]\n"
2687              "panic(cpu 0 caller 0x47f5ad): \"Process 1 exec of /sbin/launchd"
2688              " failed, errno 5\\n\"0/SourceCache/xnu/xnu-1504.15.3/bsd/kern/"
2689              "kern_exec.c:3145\n"
2690              "Debugger called: <panic>\n"
2691              "Backtrace (CPU 0), Frame : Return Address (4 potential args "
2692              "on stack)\n"
2693              "0x34bf3e48 : 0x21b837 (0x5dd7fc 0x34bf3e7c 0x223ce1 0x0)\n"
2694              "0x34bf3e98 : 0x47f5ad (0x5cf950 0x831c08 0x5 0x0)\n"
2695              "0x34bf3ef8 : 0x4696d2 (0x4800d20 0x1fe 0x45a69a0 0x80000001)\n"
2696              "0x34bf3f38 : 0x48fee5 (0x46077a8 0x84baa0 0x34bf3f88 "
2697              "0x34bf3f94)\n"
2698              "0x34bf3f68 : 0x219432 (0x46077a8 0xffffff7f 0x0 0x227c4b)\n"
2699              "0x34bf3fa8 : 0x2aacb4 (0xffffffff 0x1 0x22f8f5 0x227c4b)\n"
2700              "0x34bf3fc8 : 0x2a1976 (0x0 0x0 0x2a17ab 0x4023ef0)\n"
2701              "\n"
2702              "BSD process name corresponding to current thread: init\n"
2703              "\n"
2704              "Mac OS version:\n"
2705              "Not yet set\n"
2706              "\n"
2707              "Kernel version:\n"
2708              "Darwin Kernel version 10.8.0: Tue Jun  7 16:33:36 PDT 2011; "
2709              "root:xnu-1504.15-3~1/RELEASE_I386\n"
2710              "System model name: Macmini1,1 (Mac-F4208EC0)\n"
2711              "\n"
2712              "System uptime in nanoseconds: 13239332027\n"
2713              );
2714   BSOD_CURSOR (bst, CURSOR_BLOCK, 500000, 999999);
2715
2716   XClearWindow (dpy, window);
2717
2718   return bst;
2719 }
2720
2721
2722 /* 2017 MacOS 10.12 interminable software update, by jwz.
2723  */
2724 static struct bsod_state *
2725 macx_install (Display *dpy, Window window)
2726 {
2727   struct bsod_state *bst = make_bsod_state (dpy, window, "macinstall", "MacX");
2728
2729   Pixmap pixmap = 0;
2730   int pix_w = apple_width;
2731   int pix_h = apple_height;
2732   int x, y;
2733   int bw1, bh1;
2734   int bw2, bh2;
2735
2736   unsigned long fg = get_pixel_resource (dpy, bst->xgwa.colormap,
2737                                          "macinstall.foreground",
2738                                          "Mac.Foreground");
2739   unsigned long bg = get_pixel_resource (dpy, bst->xgwa.colormap,
2740                                          "macinstall.background",
2741                                          "Mac.Background");
2742   unsigned long fg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
2743                                          "macinstall.barForeground",
2744                                          "Mac.Foreground");
2745   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
2746                                          "macinstall.barBackground",
2747                                          "Mac.Background");
2748   char buf[1024];
2749   int lh = bst->font->ascent + bst->font->descent;
2750   int i, min;
2751   double pct;
2752
2753   bst->xoff = bst->left_margin = bst->right_margin = 0;
2754
2755   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) apple_bits,
2756                                         apple_width, apple_height,
2757                                         fg, bg, bst->xgwa.depth);
2758   bst->pixmap = pixmap;
2759
2760   x = (bst->xgwa.width - pix_w) / 2;
2761   y = (bst->xgwa.height) / 2  - pix_h;
2762   if (y < 0) y = 0;
2763
2764   XSetLineAttributes (dpy, bst->gc, 1, LineSolid, CapRound, JoinMiter);
2765
2766   BSOD_COLOR(bst, bg, bg);
2767   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
2768   BSOD_COLOR(bst, fg, bg);
2769   BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, x, y);
2770   y += pix_h * 2 - lh;
2771
2772   /* progress bar */
2773   bw1 = pix_w * 2.5;
2774   bh1 = lh * 0.66;
2775   if (bh1 < 8) bh1 = 8;
2776
2777   x = (bst->xgwa.width - bw1) / 2;
2778   BSOD_COLOR(bst, fg2, bg);
2779   BSOD_LINE (bst, x,   y, x + bw1, y, bh1);
2780
2781   bw2 = bw1 - 1;
2782   bh2 = bh1 - 4;
2783   BSOD_COLOR(bst, bg2, bg);
2784   BSOD_LINE (bst, x+1, y, x + bw2, y, bh2);
2785
2786   BSOD_COLOR(bst, fg, bg);
2787   BSOD_LINE (bst, x,   y, x + 1, y, bh1);
2788
2789   pct = 5 + (random() % 40);
2790   min = 5 + (random() % 40);
2791
2792   for (i = 0; i < 100; i++) {
2793     pct += frand(0.3);
2794     min += (random() % 3) - 1;  /* sometimes down, mostly up */
2795
2796     if (pct > 90) pct = 90;
2797     BSOD_RECT (bst, True, x, y - bh1/2, bw1 * pct / 100, bh1);
2798
2799     sprintf (buf, "  Installing Software Update: about %d minutes.  ", min);
2800     bst->y = y + lh * 3;
2801     BSOD_TEXT (bst, CENTER, buf);
2802     BSOD_PAUSE (bst, 1000000);
2803   }
2804
2805   return bst;
2806 }
2807
2808
2809 static struct bsod_state *
2810 macx (Display *dpy, Window window)
2811 {
2812 # ifdef DO_XPM
2813   switch (1?4:random() % 5) {
2814   case 0: return macx_10_0 (dpy, window);        break;
2815   case 1: return macx_10_2 (dpy, window, False); break;
2816   case 2: return macx_10_2 (dpy, window, True);  break;
2817   case 3: return mac_diskfail (dpy, window);     break;
2818   case 4: return macx_install (dpy, window);     break;
2819   default: abort();
2820   }
2821 # else  /* !DO_XPM */
2822   switch (random() % 3) {
2823   case 0:  return macx_10_0 (dpy, window);    break;
2824   case 1:  return macx_install (dpy, window); break;
2825   default: return mac_diskfail (dpy, window); break;
2826   }
2827 # endif /* !DO_XPM */
2828 }
2829
2830
2831 #ifndef HAVE_JWXYZ /* #### I have no idea how to implement this without
2832                            real plane-masks.  I don't think it would look
2833                            right if done with alpha-transparency... */
2834 /* blit damage
2835  *
2836  * by Martin Pool <mbp@samba.org>, Feb 2000.
2837  *
2838  * This is meant to look like the preferred failure mode of NCD
2839  * Xterms.  The parameters for choosing what to copy where might not
2840  * be quite right, but it looks about ugly enough.
2841  */
2842 static struct bsod_state *
2843 blitdamage (Display *dpy, Window window)
2844 {
2845   struct bsod_state *bst =
2846     make_bsod_state (dpy, window, "blitdamage", "BlitDamage");
2847
2848   int i;
2849   int delta_x = 0, delta_y = 0;
2850   int w, h;
2851   int chunk_h, chunk_w;
2852   int steps;
2853   int src_x, src_y;
2854   int x, y;
2855
2856   w = bst->xgwa.width;
2857   h = bst->xgwa.height;
2858
2859   XSetPlaneMask (dpy, bst->gc, random());
2860
2861   steps = 50;
2862   chunk_w = w / (random() % 1 + 1);
2863   chunk_h = h / (random() % 1 + 1);
2864   if (random() & 0x1000)
2865     delta_y = random() % 600;
2866   if (!delta_y || (random() & 0x2000))
2867     delta_x = random() % 600;
2868   src_x = 0;
2869   src_y = 0;
2870   x = 0;
2871   y = 0;
2872
2873   BSOD_IMG (bst);
2874   for (i = 0; i < steps; i++) {
2875     if (x + chunk_w > w)
2876       x -= w;
2877     else
2878       x += delta_x;
2879
2880     if (y + chunk_h > h)
2881       y -= h;
2882     else
2883       y += delta_y;
2884
2885     BSOD_COPY (bst, src_x, src_y, chunk_w, chunk_h, x, y);
2886     BSOD_PAUSE (bst, 1000);
2887   }
2888
2889   return bst;
2890 }
2891 #endif /* !HAVE_JWXYZ */
2892
2893
2894 /*
2895  * OS/2 panics, by Knut St. Osmundsen <bird-xscreensaver@anduin.net>
2896  *
2897  * All but one messages are real ones, some are from my test machines
2898  * and system dumps, others are reconstructed from google results.
2899  * Please, don't be to hard if the formatting of the earlier systems
2900  * aren't 100% correct.
2901  */
2902 static struct bsod_state *
2903 os2 (Display *dpy, Window window)
2904 {
2905   struct bsod_state *bst = make_bsod_state (dpy, window, "os2", "OS2");
2906
2907   __extension__
2908   static const char * const os2_panics[] =
2909     { /* OS/2 2.0 trap - details are bogus (CR0++). */
2910       "TRAP 0002       ERRCD=0000  ERACC=****  ERLIM=********\n"
2911       "EAX=7d240a58  EBX=ff202fdc  ECX=00064423  EDX=00003624\n"
2912       "ESI=fff3272c  EDI=7d240004  EBP=00004a44  FLG=00003202\n"
2913       "CS:EIP=0160:fff702a6  CSACC=c09d  CSLIM=ffffffff\n"
2914       "SS:ESP=0030:00004a38  SSACC=1097  SSLIM=00003fff\n"
2915       "DS=0158  DSACC=c0f3  DSLIM=ffffffff  CR0=fffffffb\n"
2916       "ES=0158  ESACC=c0f3  ESLIM=ffffffff  CR2=1a060014\n"
2917       "FS=0000  FSACC=****  FSLIM=********\n"
2918       "GS=0000  GSACC=****  GSLIM=********\n"
2919       "\n"
2920       "The system detected an internal processing error\n"
2921       "at location ##0160:fff6453f - 000d:a53f\n"
2922       "60000, 9084\n"
2923       "\n"
2924       "038600d1\n"
2925       "Internal revision 6.307, 92/03/01\n"
2926       "\n",
2927
2928       /* warp 3 (early) */
2929       "TRAP 000e       ERRCD=0000  ERACC=****  ERLIM=********\n"
2930       "EAX=ff050c20  EBX=000000bb  ECX=ffff00c1  EDx=fff379b8\n"
2931       "ESI=ffe55a3c  EDI=00000000  EBP=00004eb8  FLG=00013282\n"
2932       "CS:EIP=0160:fff8dbb8  CSACC=c09b  CSLIM=ffffffff\n"
2933       "SS:EIP=0030:00004eb4  SSACC=1097  SSLIM=00003fff\n"
2934       "DS=0158  DSACC=c0f3  DSLIM=ffffffff  CR0=8001001b\n"
2935       "ES=0158  DSACC=c0f3  DSLIM=ffffffff  CR2=000000c7\n"
2936       "FS=0000  FSACC=****  FSLIM=********\n"
2937       "GS=0000  GSACC=****  GSLIM=********\n"
2938       "\n"
2939       "The system detected an internal processing error\n"
2940       "at location ##0160:fff66bf0 - 000d:9bf0.\n"
2941       "60000, 9084\n"
2942       "\n"
2943       "048600b4\n"
2944       "Internal revision 8.125, 94/02/16\n"
2945       "\n"
2946       "The system is stopped.  Record the location number of the error\n"
2947       "and contact your service representative.\n",
2948
2949       /* warp 3 */
2950       "TRAP 000e       ERRCD=0002  ERACC=****  ERLIM=********\n"
2951       "EAX=00000000  EBX=fdef1e0c  ECX=00003824  EDX=0000edf9\n"
2952       "ESI=fdf30e80  EDI=fc8b0000  EBP=00005658  FLG=00012246\n"
2953       "CS:EIP=0160:fff8ada3  CSACC=c09b  CSLIM=ffffffff\n"
2954       "SS:ESP=0030:000055d4  SSACC=1097  SSLIM=0000480f\n"
2955       "DS=0158  DSACC=c093  DSLIM=ffffffff  CR0=8001001b\n"
2956       "ES=0158  ESACC=c093  ESLIM=ffffffff  CR2=fc8b0000\n"
2957       "FS=03b8  FSACC=0093  FSLIM=00000023\n"
2958       "GS=0000  GSACC=****  GSLIM=********\n"
2959       "\n"
2960       "The system detected an internal processing error\n"
2961       "at location ##0160:fff5c364 - 000d:a364.\n"
2962       "60000, 9084\n"
2963       "\n"
2964       "05860526\n"
2965       "Internal revision 8200,94/11/07\n"
2966       "\n"
2967       "The system is stopped. Record all of the above information and\n"
2968       "contact your service representative.\n",
2969
2970       /* warp 3 (late) */
2971       "TRAP 000d       ERRCD=2200  ERACC=1092  ERLIM=00010fff\n"
2972       "EAX=0000802e  EBX=fff001c8  ECX=9bd80000  EDX=00000000\n"
2973       "ESI=fff09bd8  EDI=fdeb001b  EBP=00000000  FLG=00012012\n"
2974       "CS:EIP=0168:fff480a2  CSACC=c09b  CSLIM=ffffffff\n"
2975       "SS:ESP=00e8:00001f32  SSACC=0093  SSLIM=00001fff\n"
2976       "DS=0940  DSACC=0093  DSLIM=00000397  CR0=8001001b\n"
2977       "ES=00e8  ESACC=0093  ESLIM=00001fff  CR2=15760008\n"
2978       "FS=0000  FSACC=****  FSLIM=****\n"
2979       "GS=0000  GSACC=****  GSLIM=****\n"
2980       "\n"
2981       "The system detected an internal processing error\n"
2982       "at location ##0168:fff4b06e - 000e:c06e\n"
2983       "60000, 9084\n"
2984       "\n"
2985       "06860652\n"
2986       "Internal revision 8.259_uni,98/01/07\n"
2987       "\n"
2988       "The system is stopped. Record all of the above information and\n"
2989       "contact your service representative.\n",
2990
2991       /* Warp 4.52+ - the official r0trap.exe from the debugging classes */
2992       "Exception in module: OS2KRNL\n"
2993       "TRAP 000e       ERRCD=0002  ERACC=****  ERLIM=********\n"
2994       "EAX=00000001  EBX=80010002  ECX=ffed4638  EDX=0003f17b\n"
2995       "ESI=00000001  EDI=00000002  EBP=00005408  FLG=00012202\n"
2996       "CS:EIP=0168:fff3cd2e  CSACC=c09b  CSLIM=ffffffff\n"
2997       "SS:ESP=0030:000053ec  SSACC=1097  SSLIM=000044ff\n"
2998       "DS=0160  DSACC=c093  DSLIM=ffffffff  CR0=8001001b\n"
2999       "ES=0160  ESACC=c093  ESLIM=ffffffff  CR2=00000001\n"
3000       "FS=0000  FSACC=****  FSLIM=********\n"
3001       "GS=0000  GSACC=****  GSLIM=********\n"
3002       "\n"
3003       "The system detected an internal processing error at\n"
3004       "location ##0168:fff1e3f3 - 000e:c3f3.\n"
3005       "60000, 9084\n"
3006       "\n"
3007       "068606a0\n"
3008       "Internal revision 14.097_UNI\n"
3009       "\n"
3010       "The system is stopped. Record all of the above information and\n"
3011       "contact your service representative.\n",
3012
3013       /* Warp 4.52+, typical JFS problem. */
3014       "Exeption in module: JFS\n"
3015       "TRAP 0003       ERRCD=0000  ERACC=****  ERLIM=********\n"
3016       "EAX=00000000  EBX=ffffff05  ECX=00000001  EDX=f5cd8010\n"
3017       "ESI=000000e6  EDI=000000e7  EBP=f9c7378e  FLG=00002296\n"
3018       "CS:EIP=0168:f8df3250  CSACC=c09b  CSLIM=ffffffff\n"
3019       "SS:ESP=1550:fdc73778  SSACC=c093  SSLIM=ffffffff\n"
3020       "DS=0160  DSACC=c093  DSLIM=ffffffff  CR0=80010016\n"
3021       "ES=0160  ESACC=c093  DSLIM=ffffffff  CR2=05318000\n"
3022       "FS=03c0  FSACC=0093  DSLIM=00000023\n"
3023       "GS=0160  GSACC=c093  DSLIM=ffffffff\n"
3024       "\n"
3025       "The system detected an internal processing error\n"
3026       "at location ##0168:fff1e2ab - 000e:c2ab.\n"
3027       "60000, 9084\n"
3028       "\n"
3029       "07860695\n"
3030       "\n"
3031       "Internal revision 14.100c_UNI\n"
3032       "\n"
3033       "The system is stopped. Record all of the above information and\n"
3034       "contact your service representative.\n"
3035     };
3036
3037   BSOD_TEXT (bst, LEFT, os2_panics[random() % countof(os2_panics)]);
3038   BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999);
3039
3040   XClearWindow (dpy, window);
3041   return bst;
3042 }
3043
3044
3045 /* SPARC Solaris panic. Should look pretty authentic on Solaris boxes.
3046  * Anton Solovyev <solovam@earthlink.net>
3047  */
3048 static struct bsod_state *
3049 sparc_solaris (Display *dpy, Window window)
3050 {
3051   struct bsod_state *bst = make_bsod_state (dpy, window, "solaris", "Solaris");
3052   int i;
3053
3054   bst->scroll_p = True;
3055   bst->wrap_p = True;
3056   bst->left_margin = bst->right_margin = bst->xgwa.width  * 0.07;
3057   bst->top_margin = bst->bottom_margin = bst->xgwa.height * 0.07;
3058   bst->y = bst->top_margin + bst->yoff + bst->font->ascent;
3059
3060   BSOD_IMG (bst);
3061   BSOD_PAUSE (bst, 3000000);
3062
3063   BSOD_INVERT(bst);
3064   BSOD_RECT (bst, True,
3065              bst->left_margin, bst->top_margin,
3066              bst->xgwa.width - bst->left_margin - bst->right_margin,
3067              bst->xgwa.height - bst->top_margin - bst->bottom_margin);
3068   BSOD_INVERT(bst);
3069
3070   BSOD_TEXT (bst, LEFT,
3071     "BAD TRAP: cpu=0 type=0x31 rp=0x2a10043b5e0 addr=0xf3880 mmu_fsr=0x0\n"
3072     "BAD TRAP occurred in module \"unix\" due to an illegal access to a"
3073     " user address.\n"
3074     "adb: trap type = 0x31\n"
3075     "addr=0xf3880\n"
3076     "pid=307, pc=0x100306e4, sp=0x2a10043ae81, tstate=0x4480001602,"
3077     " context=0x87f\n"
3078     "g1-g7: 1045b000, 32f, 10079440, 180, 300000ebde8, 0, 30000953a20\n"
3079     "Begin traceback... sp = 2a10043ae81\n"
3080     "Called from 100bd060, fp=2a10043af31, args=f3700 300008cc988 f3880 0"
3081     " 1 300000ebde0.\n"
3082     "Called from 101fe1bc, fp=2a10043b011, args=3000045a240 104465a0"
3083     " 300008e47d0 300008e48fa 300008ae350 300008ae410\n"
3084     "Called from 1007c520, fp=2a10043b0c1, args=300008e4878 300003596e8 0"
3085     " 3000045a320 0 3000045a220\n"
3086     "Called from 1007c498, fp=2a10043b171, args=1045a000 300007847f0 20"
3087     " 3000045a240 1 0\n"
3088     "Called from 1007972c, fp=2a10043b221, args=1 300009517c0 30000951e58 1"
3089     " 300007847f0 0\n"
3090     "Called from 10031e10, fp=2a10043b2d1, args=3000095b0c8 0 300009396a8"
3091     " 30000953a20 0 1\n"
3092     "Called from 10000bdd8, fp=ffffffff7ffff1c1, args=0 57 100131480"
3093     " 100131480 10012a6e0 0\n"
3094     "End traceback...\n"
3095     "panic[cpu0]/thread=30000953a20: trap\n"
3096     "syncing file systems...");
3097
3098   BSOD_PAUSE (bst, 3000000);
3099
3100   BSOD_TEXT (bst, LEFT, " 1 done\n");
3101   BSOD_TEXT (bst, LEFT, "dumping to /dev/dsk/c0t0d0s3, offset 26935296\n");
3102   BSOD_PAUSE (bst, 2000000);
3103
3104
3105   for (i = 1; i <= 100; ++i)
3106     {
3107       char buf[100];
3108       sprintf (buf, "\b\b\b\b\b\b\b\b\b\b\b%3d%% done", i);
3109       BSOD_TEXT (bst, LEFT, buf);
3110       BSOD_PAUSE (bst, 100000);
3111     }
3112
3113   BSOD_TEXT (bst, LEFT,
3114     ": 2803 pages dumped, compression ratio 2.88, dump succeeded\n");
3115   BSOD_PAUSE (bst, 2000000);
3116
3117   BSOD_TEXT (bst, LEFT,
3118     "rebooting...\n"
3119     "Resetting ...");
3120
3121   return bst;
3122 }
3123
3124
3125 /* Linux panic and fsck, by jwz
3126  */
3127 static struct bsod_state *
3128 linux_fsck (Display *dpy, Window window)
3129 {
3130   struct bsod_state *bst = make_bsod_state (dpy, window, "linux", "Linux");
3131
3132   int i;
3133   const char *sysname;
3134   char buf[1024];
3135 # ifdef HAVE_UNAME
3136   struct utsname uts;
3137 #endif /* UNAME */
3138
3139   const char *linux_panic[] = {
3140    " kernel: Unable to handle kernel paging request at virtual "
3141      "address 0000f0ad\n",
3142    " kernel:  printing eip:\n",
3143    " kernel: c01becd7\n",
3144    " kernel: *pde = 00000000\n",
3145    " kernel: Oops: 0000\n",
3146    " kernel: CPU:    0\n",
3147    " kernel: EIP:    0010:[<c01becd7>]    Tainted: P \n",
3148    " kernel: EFLAGS: 00010286\n",
3149    " kernel: eax: 0000ff00   ebx: ca6b7e00   ecx: ce1d7a60   edx: ce1d7a60\n",
3150    " kernel: esi: ca6b7ebc   edi: 00030000   ebp: d3655ca0   esp: ca6b7e5c\n",
3151    " kernel: ds: 0018   es: 0018   ss: 0018\n",
3152    " kernel: Process crond (pid: 1189, stackpage=ca6b7000)\n",
3153    " kernel: Stack: d3655ca0 ca6b7ebc 00030054 ca6b7e7c c01c1e5b "
3154        "00000287 00000020 c01c1fbf \n",
3155    "",
3156    " kernel:        00005a36 000000dc 000001f4 00000000 00000000 "
3157        "ce046d40 00000001 00000000 \n",
3158    "", "", "",
3159    " kernel:        ffffffff d3655ca0 d3655b80 00030054 c01bef93 "
3160        "d3655ca0 ca6b7ebc 00030054 \n",
3161    "", "", "",
3162    " kernel: Call Trace:    [<c01c1e5b>] [<c01c1fbf>] [<c01bef93>] "
3163        "[<c01bf02b>] [<c0134c4f>]\n",
3164    "", "", "",
3165    " kernel:   [<c0142562>] [<c0114f8c>] [<c0134de3>] [<c010891b>]\n",
3166    " kernel: \n",
3167    " kernel: Code: 2a 00 75 08 8b 44 24 2c 85 c0 74 0c 8b 44 24 58 83 48 18 "
3168       "08 \n",
3169    0
3170   };
3171
3172   bst->scroll_p = True;
3173   bst->wrap_p = True;
3174   bst->left_margin = bst->right_margin = 10;
3175   bst->top_margin = bst->bottom_margin = 10;
3176
3177   sysname = "linux";
3178 # ifdef HAVE_UNAME
3179   {
3180     char *s;
3181     if (uname (&uts) >= 0)
3182       sysname = uts.nodename;
3183     s = strchr (sysname, '.');
3184     if (s) *s = 0;
3185   }
3186 # endif /* !HAVE_UNAME */
3187
3188
3189   BSOD_TEXT (bst, LEFT, "waiting for X server to shut down ");
3190   BSOD_PAUSE (bst, 100000);
3191   BSOD_TEXT (bst, LEFT,
3192              "XIO:  fatal IO error 2 (broken pipe) on X server \":0.0\"\n"
3193              "        after 339471 requests (339471 known processed) "
3194              "with 0 events remaining\n");
3195   BSOD_CHAR_DELAY (bst, 300000);
3196   BSOD_TEXT (bst, LEFT, ".........\n");
3197   BSOD_CHAR_DELAY (bst, 0);
3198   BSOD_TEXT (bst, LEFT,
3199              "xinit:  X server slow to shut down, sending KILL signal.\n"
3200              "waiting for server to die ");
3201   BSOD_CHAR_DELAY (bst, 300000);
3202   BSOD_TEXT (bst, LEFT, "...\n");
3203   BSOD_CHAR_DELAY (bst, 0);
3204   BSOD_TEXT (bst, LEFT, "xinit:  Can't kill server\n");
3205   BSOD_PAUSE (bst, 2000000);
3206
3207   sprintf (buf, "\n%s Login: ", sysname);
3208   BSOD_TEXT (bst, LEFT, buf);
3209   BSOD_PAUSE (bst, 1000000);
3210   BSOD_TEXT (bst, LEFT,
3211     "\n\n"
3212     "Parallelizing fsck version 1.22 (22-Jun-2001)\n"
3213     "e2fsck 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09\n"
3214     "Warning!  /dev/hda1 is mounted.\n"
3215     "/dev/hda1 contains a file system with errors, check forced.\n");
3216   BSOD_PAUSE (bst, 1000000);
3217
3218   if (0 == random() % 2)
3219     BSOD_TEXT (bst, LEFT,
3220      "Couldn't find ext2 superblock, trying backup blocks...\n"
3221      "The filesystem size (according to the superblock) is 3644739 blocks\n"
3222      "The physical size of the device is 3636706 blocks\n"
3223      "Either the superblock or the partition table is likely to be corrupt!\n"
3224      "Abort<y>? no\n");
3225   BSOD_PAUSE (bst, 1000000);
3226
3227  AGAIN:
3228
3229   BSOD_TEXT (bst, LEFT, "Pass 1: Checking inodes, blocks, and sizes\n");
3230   BSOD_PAUSE (bst, 2000000);
3231
3232   i = (random() % 60) - 20;
3233   while (--i > 0)
3234     {
3235       int b = random() % 0xFFFF;
3236       sprintf (buf, "Deleted inode %d has zero dtime.  Fix<y>? yes\n\n", b);
3237       BSOD_TEXT (bst, LEFT, buf);
3238       BSOD_PAUSE (bst, 1000);
3239     }
3240
3241   i = (random() % 40) - 10;
3242   if (i > 0)
3243     {
3244       int g = random() % 0xFFFF;
3245       int b = random() % 0xFFFFFFF;
3246
3247       BSOD_PAUSE (bst, 1000000);
3248
3249       sprintf (buf, "Warning: Group %d's copy of the group descriptors "
3250                "has a bad block (%d).\n", g, b);
3251       BSOD_TEXT (bst, LEFT, buf);
3252
3253       b = random() % 0x3FFFFF;
3254       while (--i > 0)
3255         {
3256           b += random() % 0xFFFF;
3257           sprintf (buf,
3258                    "Error reading block %d (Attempt to read block "
3259                    "from filesystem resulted in short read) while doing "
3260                    "inode scan.  Ignore error<y>?",
3261                    b);
3262           BSOD_TEXT (bst, LEFT, buf);
3263           BSOD_PAUSE (bst, 10000);
3264           BSOD_TEXT (bst, LEFT, " yes\n\n");
3265         }
3266     }
3267
3268   if (0 == (random() % 10))
3269     {
3270       BSOD_PAUSE (bst, 1000000);
3271
3272       i = 3 + (random() % 10);
3273       while (--i > 0)
3274         {
3275           BSOD_TEXT (bst, LEFT,
3276                      "Could not allocate 256 block(s) for inode table: "
3277                      "No space left on device\n");
3278           BSOD_PAUSE (bst, 1000);
3279         }
3280       BSOD_TEXT (bst, LEFT, "Restarting e2fsck from the beginning...\n");
3281       BSOD_PAUSE (bst, 2000000);
3282
3283       goto AGAIN;
3284     }
3285
3286   i = (random() % 20) - 5;
3287
3288   if (i > 0)
3289     BSOD_PAUSE (bst, 1000000);
3290
3291   while (--i > 0)
3292     {
3293       int j = 5 + (random() % 10);
3294       int w = random() % 4;
3295
3296       while (--j > 0)
3297         {
3298           int b = random() % 0xFFFFF;
3299           int g = random() % 0xFFF;
3300
3301           if (0 == (random() % 10))
3302             b = 0;
3303           else if (0 == (random() % 10))
3304             b = -1;
3305
3306           if (w == 0)
3307             sprintf (buf,
3308                      "Inode table for group %d not in group.  (block %d)\n"
3309                      "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
3310                      "Relocate<y>?",
3311                      g, b);
3312           else if (w == 1)
3313             sprintf (buf,
3314                      "Block bitmap for group %d not in group.  (block %d)\n"
3315                      "Relocate<y>?",
3316                      g, b);
3317           else if (w == 2)
3318             sprintf (buf,
3319                      "Inode bitmap %d for group %d not in group.\n"
3320                      "Continue<y>?",
3321                      b, g);
3322           else /* if (w == 3) */
3323             sprintf (buf,
3324                      "Bad block %d in group %d's inode table.\n"
3325                      "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
3326                      "Relocate<y>?",
3327                      b, g);
3328
3329           BSOD_TEXT (bst, LEFT, buf);
3330           BSOD_TEXT (bst, LEFT, " yes\n\n");
3331           BSOD_PAUSE (bst, 1000);
3332         }
3333     }
3334
3335
3336   if (0 == random() % 10) goto PANIC;
3337   BSOD_TEXT (bst, LEFT, "Pass 2: Checking directory structure\n");
3338   BSOD_PAUSE (bst, 2000000);
3339
3340   i = (random() % 20) - 5;
3341   while (--i > 0)
3342     {
3343       int n = random() % 0xFFFFF;
3344       int o = random() % 0xFFF;
3345       sprintf (buf, "Directory inode %d, block 0, offset %d: "
3346                "directory corrupted\n"
3347                "Salvage<y>? ",
3348                n, o);
3349       BSOD_TEXT (bst, LEFT, buf);
3350       BSOD_PAUSE (bst, 1000);
3351       BSOD_TEXT (bst, LEFT, " yes\n\n");
3352
3353       if (0 == (random() % 100))
3354         {
3355           sprintf (buf, "Missing '.' in directory inode %d.\nFix<y>?", n);
3356           BSOD_TEXT (bst, LEFT, buf);
3357           BSOD_PAUSE (bst, 1000);
3358           BSOD_TEXT (bst, LEFT, " yes\n\n");
3359         }
3360     }
3361
3362   if (0 == random() % 10)
3363     goto PANIC;
3364
3365   BSOD_TEXT (bst, LEFT,
3366              "Pass 3: Checking directory connectivity\n"
3367              "/lost+found not found.  Create? yes\n");
3368   BSOD_PAUSE (bst, 2000000);
3369
3370   /* Unconnected directory inode 4949 (/var/spool/squid/06/???)
3371      Connect to /lost+found<y>? yes
3372
3373      '..' in /var/spool/squid/06/08 (20351) is <The NULL inode> (0), should be
3374      /var/spool/squid/06 (20350).
3375      Fix<y>? yes
3376
3377      Unconnected directory inode 128337 (/var/spool/squid/06/???)
3378      Connect to /lost+found<y>? yes
3379    */
3380
3381
3382   if (0 == random() % 10) goto PANIC;
3383   BSOD_TEXT (bst, LEFT,  "Pass 4: Checking reference counts\n");
3384   BSOD_PAUSE (bst, 2000000);
3385
3386   /* Inode 2 ref count is 19, should be 20.  Fix<y>? yes
3387
3388      Inode 4949 ref count is 3, should be 2.  Fix<y>? yes
3389
3390         ...
3391
3392      Inode 128336 ref count is 3, should be 2.  Fix<y>? yes
3393
3394      Inode 128337 ref count is 3, should be 2.  Fix<y>? yes
3395
3396    */
3397
3398
3399   if (0 == random() % 10) goto PANIC;
3400   BSOD_TEXT (bst, LEFT,  "Pass 5: Checking group summary information\n");
3401   BSOD_PAUSE (bst, 2000000);
3402
3403   i = (random() % 200) - 50;
3404   if (i > 0)
3405     {
3406       BSOD_TEXT (bst, LEFT,  "Block bitmap differences: ");
3407       while (--i > 0)
3408         {
3409           sprintf (buf, " %d", -(random() % 0xFFF));
3410           BSOD_TEXT (bst, LEFT, buf);
3411           BSOD_PAUSE (bst, 1000);
3412         }
3413       BSOD_TEXT (bst, LEFT, "\nFix? yes\n\n");
3414     }
3415
3416
3417   i = (random() % 100) - 50;
3418   if (i > 0)
3419     {
3420       BSOD_TEXT (bst, LEFT,  "Inode bitmap differences: ");
3421       while (--i > 0)
3422         {
3423           sprintf (buf, " %d", -(random() % 0xFFF));
3424           BSOD_TEXT (bst, LEFT, buf);
3425           BSOD_PAUSE (bst, 1000);
3426         }
3427       BSOD_TEXT (bst, LEFT,  "\nFix? yes\n\n");
3428     }
3429
3430   i = (random() % 20) - 5;
3431   while (--i > 0)
3432     {
3433       int g = random() % 0xFFFF;
3434       int c = random() % 0xFFFF;
3435       sprintf (buf,
3436                "Free blocks count wrong for group #0 (%d, counted=%d).\nFix? ",
3437                g, c);
3438       BSOD_TEXT (bst, LEFT, buf);
3439       BSOD_PAUSE (bst, 1000);
3440       BSOD_TEXT (bst, LEFT,  " yes\n\n");
3441     }
3442
3443  PANIC:
3444
3445   i = 0;
3446   BSOD_TEXT (bst, LEFT,  "\n\n");
3447   while (linux_panic[i])
3448     {
3449       time_t t = time ((time_t *) 0);
3450       struct tm *tm = localtime (&t);
3451       char prefix[100];
3452
3453       if (*linux_panic[i])
3454         {
3455           strftime (prefix, sizeof(prefix)-1, "%b %d %H:%M:%S ", tm);
3456           BSOD_TEXT (bst, LEFT,  prefix);
3457           BSOD_TEXT (bst, LEFT,  sysname);
3458           BSOD_TEXT (bst, LEFT,  linux_panic[i]);
3459           BSOD_PAUSE (bst, 1000);
3460         }
3461       else
3462         BSOD_PAUSE (bst, 300000);
3463
3464       i++;
3465     }
3466   BSOD_PAUSE (bst, 4000000);
3467
3468   XClearWindow(dpy, window);
3469   return bst;
3470 }
3471
3472
3473 /*
3474  * Linux (hppa) panic, by Stuart Brady <sdbrady@ntlworld.com>
3475  * Output courtesy of M. Grabert
3476  */
3477 static struct bsod_state *
3478 hppa_linux (Display *dpy, Window window)
3479 {
3480   struct bsod_state *bst =
3481     make_bsod_state (dpy, window, "hppalinux", "HPPALinux");
3482
3483   int i = 0;
3484   const char *release, *sysname, *gccversion, *version;
3485   long int linedelay = 0;
3486   char ss[1024];
3487 # ifdef HAVE_UNAME
3488   struct utsname uts;
3489 # endif /* UNAME */
3490
3491   __extension__
3492   struct { long int delay; const char *string; } linux_panic[] =
3493     {{ 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"
3494           "\n\n\n\n\n\n\n\n\n\n\n\n\n" },
3495      { 0, "Linux version %s (root@%s) (gcc version %s) %s\n" },
3496      { 4000, "FP[0] enabled: Rev 1 Model 16\n" },
3497      { 10, "The 32-bit Kernel has started...\n" },
3498      { -1, "Determining PDC firmware type: System Map.\n" },
3499      { -1, "model 00005bb0 00000481 00000000 00000002 7778df9f 100000f0 "
3500            "00000008 000000b2 000000b2\n" },
3501      { -1, "vers  00000203\n" },
3502      { -1, "CPUID vers 17 rev 7 (0x00000227)\n" },
3503      { -1, "capabilities 0x3\n" },
3504      { -1, "model 9000/785/C3000\n" },
3505      { -1, "Total Memory: 1024 Mb\n" },
3506      { -1, "On node 0 totalpages: 262144\n" },
3507      { -1, "  DMA zone: 262144 pages, LIFO batch:16\n" },
3508      { -1, "  Normal zone: 0 pages, LIFO batch:1\n" },
3509      { -1, "  HighMem zone: 0 pages, LIFO batch:1\n" },
3510      { -1, "LCD display at f05d0008,f05d0000 registered\n" },
3511      { -1, "Building zonelist for node : 0\n" },
3512      { -1, "Kernel command line: ide=nodma root=/dev/sda3 HOME=/ ip=off "
3513            "console=ttyS0 TERM=vt102 palo_kernel=2/vmlinux-2.6\n" },
3514      { -1, "ide_setup: ide=nodmaIDE: Prevented DMA\n" },
3515      { -1, "PID hash table entries: 16 (order 4: 128 bytes)\n" },
3516      {500, "Console: colour dummy device 160x64\n" },
3517      { 10, "Memory: 1034036k available\n" },
3518      { -1, "Calibrating delay loop... 796.67 BogoMIPS\n" },
3519      { -1, "Dentry cache hash table entries: 131072 (order: 7, 524288 "
3520            "bytes)\n" },
3521      { -1, "Inode-cache hash table entries: 65536 (order: 6, 262144 "
3522            "bytes)\n" },
3523      { -1, "Mount-cache hash table entries: 512 (order: 0, 4096 bytes)\n" },
3524      { -1, "POSIX conformance testing by UNIFIX\n" },
3525      { -1, "NET: Registered protocol family 16\n" },
3526      { 100, "Searching for devices...\n" },
3527      { 25, "Found devices:\n" },
3528      { 10, "1. Astro BC Runway Port at 0xfed00000 [10] "
3529            "{ 12, 0x0, 0x582, 0x0000b }\n" },
3530      { -1, "2. Elroy PCI Bridge at 0xfed30000 [10/0] "
3531            "{ 13, 0x0, 0x782, 0x0000a }\n" },
3532      { -1, "3. Elroy PCI Bridge at 0xfed32000 [10/1] "
3533            "{ 13, 0x0, 0x782, 0x0000a }\n" },
3534      { -1, "4. Elroy PCI Bridge at 0xfed38000 [10/4] "
3535            "{ 13, 0x0, 0x782, 0x0000a }\n" },
3536      { -1, "5. Elroy PCI Bridge at 0xfed3c000 [10/6] "
3537            "{ 13, 0x0, 0x782, 0x0000a }\n" },
3538      { -1, "6. AllegroHigh W at 0xfffa0000 [32] "
3539            "{ 0, 0x0, 0x5bb, 0x00004 }\n" },
3540      { -1, "7. Memory at 0xfed10200 [49] { 1, 0x0, 0x086, 0x00009 }\n" },
3541      { -1, "CPU(s): 1 x PA8500 (PCX-W) at 400.000000 MHz\n" },
3542      { -1, "SBA found Astro 2.1 at 0xfed00000\n" },
3543      { -1, "lba version TR2.1 (0x2) found at 0xfed30000\n" },
3544      { -1, "lba version TR2.1 (0x2) found at 0xfed32000\n" },
3545      { -1, "lba version TR2.1 (0x2) found at 0xfed38000\n" },
3546      { -1, "lba version TR2.1 (0x2) found at 0xfed3c000\n" },
3547      { 100, "SCSI subsystem initialized\n" },
3548      { 10, "drivers/usb/core/usb.c: registered new driver usbfs\n" },
3549      { -1, "drivers/usb/core/usb.c: registered new driver hub\n" },
3550      { -1, "ikconfig 0.7 with /proc/config*\n" },
3551      { -1, "Initializing Cryptographic API\n" },
3552      { 250, "SuperIO: probe of 0000:00:0e.0 failed with error -1\n" },
3553      { 20, "SuperIO: Found NS87560 Legacy I/O device at 0000:00:0e.1 "
3554            "(IRQ 64)\n" },
3555      { -1, "SuperIO: Serial port 1 at 0x3f8\n" },
3556      { -1, "SuperIO: Serial port 2 at 0x2f8\n" },
3557      { -1, "SuperIO: Parallel port at 0x378\n" },
3558      { -1, "SuperIO: Floppy controller at 0x3f0\n" },
3559      { -1, "SuperIO: ACPI at 0x7e0\n" },
3560      { -1, "SuperIO: USB regulator enabled\n" },
3561      { -1, "SuperIO: probe of 0000:00:0e.2 failed with error -1\n" },
3562      { -1, "Soft power switch enabled, polling @ 0xf0400804.\n" },
3563      { -1, "pty: 256 Unix98 ptys configured\n" },
3564      { -1, "Generic RTC Driver v1.07\n" },
3565      { -1, "Serial: 8250/16550 driver $" "Revision: 1.100 $ 13 ports, "
3566            "IRQ sharing disabled\n" },
3567      { -1, "ttyS0 at I/O 0x3f8 (irq = 0) is a 16550A\n" },
3568      { -1, "ttyS1 at I/O 0x2f8 (irq = 0) is a 16550A\n" },
3569      { -1, "Linux Tulip driver version 1.1.13 (May 11, 2002)\n" },
3570      { 150, "tulip0: no phy info, aborting mtable build\n" },
3571      { 10, "tulip0:  MII transceiver #1 config 1000 status 782d "
3572            "advertising 01e1.\n" },
3573      { -1, "eth0: Digital DS21143 Tulip rev 65 at 0xf4008000, "
3574            "00:10:83:F9:B4:34, IRQ 66.\n" },
3575      { -1, "Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2\n" },
3576      { -1, "ide: Assuming 33MHz system bus speed for PIO modes; "
3577            "override with idebus=xx\n" },
3578      { 100, "SiI680: IDE controller at PCI slot 0000:01:06.0\n" },
3579      { 10, "SiI680: chipset revision 2\n" },
3580      { -1, "SiI680: BASE CLOCK == 133\n" },
3581      { -1, "SiI680: 100% native mode on irq 128\n" },
3582      { -1, "    ide0: MMIO-DMA at 0xf4800000-0xf4800007 -- "
3583            "Error, MMIO ports already in use.\n" },
3584      { -1, "    ide1: MMIO-DMA at 0xf4800008-0xf480000f -- "
3585            "Error, MMIO ports already in use.\n" },
3586      { 5, "hda: TS130220A2, ATA DISK drive\n" },
3587      { -1, "      _______________________________\n" },
3588      { -1, "     < Your System ate a SPARC! Gah! >\n" },
3589      { -1, "      -------------------------------\n" },
3590      { -1, "             \\   ^__^\n" },
3591      { -1, "              \\  (xx)\\_______\n" },
3592      { -1, "                 (__)\\       )\\/\\\n" },
3593      { -1, "                  U  ||----w |\n" },
3594      { -1, "                     ||     ||\n" },
3595      { -1, "swapper (pid 1): Breakpoint (code 0)\n" },
3596      { -1, "\n" },
3597      { -1, "     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n" },
3598      { -1, "PSW: 00000000000001001111111100001111 Not tainted\n" },
3599      { -1, "r00-03  4d6f6f21 1032f010 10208f34 103fc2e0\n" },
3600      { -1, "r04-07  103fc230 00000001 00000001 0000000f\n" },
3601      { -1, "r08-11  103454f8 000f41fa 372d3980 103ee404\n" },
3602      { -1, "r12-15  3ccbf700 10344810 103ee010 f0400004\n" },
3603      { -1, "r16-19  f00008c4 f000017c f0000174 00000000\n" },
3604      { -1, "r20-23  fed32840 fed32800 00000000 0000000a\n" },
3605      { -1, "r24-27  0000ffa0 000000ff 103fc2e0 10326010\n" },
3606      { -1, "r28-31  00000000 00061a80 4ff98340 10208f34\n" },
3607      { -1, "sr0-3   00000000 00000000 00000000 00000000\n" },
3608      { -1, "sr4-7   00000000 00000000 00000000 00000000\n" },
3609      { -1, "\n" },
3610      { -1, "IASQ: 00000000 00000000 IAOQ: 00000000 00000004\n" },
3611      { -1, " IIR: 00000000    ISR: 00000000  IOR: 00000000\n" },
3612      { -1, " CPU:        0   CR30: 4ff98000 CR31: 1037c000\n" },
3613      { -1, " ORIG_R28: 55555555\n" },
3614      { -1, " IAOQ[0]: 0x0\n" },
3615      { -1, " IAOQ[1]: 0x4\n" },
3616      { -1, " RP(r2): probe_hwif+0x218/0x44c\n" },
3617      { -1, "Kernel panic: Attempted to kill init!\n" },
3618      { 0, NULL }};
3619
3620   bst->scroll_p = True;
3621   bst->wrap_p = True;
3622   bst->left_margin = bst->right_margin = 10;
3623   bst->top_margin = bst->bottom_margin = 10;
3624
3625   release = "2.6.0-test11-pa2";
3626   sysname = "hppa";
3627   version = "#2 Mon Dec 8 06:09:27 GMT 2003";
3628 # ifdef HAVE_UNAME
3629   {
3630     char *s;
3631     if (uname (&uts) >= 0)
3632       {
3633         sysname = uts.nodename;
3634         if (!strcmp (uts.sysname, "Linux"))
3635           {
3636             release = uts.release;
3637             version = uts.version;
3638           }
3639       }
3640     s = strchr (sysname, '.');
3641     if (s) *s = 0;
3642   }
3643 # endif /* !HAVE_UNAME */
3644
3645 # if (defined (__GNUC__) && defined (__VERSION__))
3646   gccversion = __VERSION__;
3647 # else /* !(defined (__GNUC__) && defined (__VERSION__)) */
3648   gccversion = "3.3.2 (Debian)";
3649 # endif /* !(defined (__GNUC__) && defined (__VERSION__)) */
3650
3651   /* Insert current host name into banner on line 2 */
3652   {
3653     snprintf (ss, 1024, linux_panic[1].string,
3654               release, sysname, gccversion, version);
3655     linux_panic[1].string = ss;
3656   }
3657
3658   BSOD_PAUSE (bst, 100000);
3659   while (linux_panic[i].string)
3660     {
3661       if (linux_panic[i].delay != -1)
3662         linedelay = linux_panic[i].delay * 1000;
3663       BSOD_PAUSE (bst, linedelay);
3664       BSOD_TEXT (bst, LEFT, linux_panic[i].string);
3665       i++;
3666     }
3667
3668   bst->y = bst->xgwa.height - bst->yoff
3669     - bst->font->ascent - bst->font->descent;
3670
3671   XClearWindow(dpy, window);
3672   return bst;
3673 }
3674
3675
3676 /* VMS by jwz (text sent by Roland Barmettler <roli@barmettler.net>)
3677  */
3678 static struct bsod_state *
3679 vms (Display *dpy, Window window)
3680 {
3681   struct bsod_state *bst = make_bsod_state (dpy, window, "vms", "VMS");
3682
3683   const char *sysname;
3684   int char_delay = 0;
3685   int dot_delay = 40000;
3686   int chunk_delay = 500000;
3687   char *s, *s1;
3688   int i;
3689   int arg_count;
3690 # ifdef HAVE_UNAME
3691   struct utsname uts;
3692 # endif /* UNAME */
3693
3694   __extension__
3695
3696   const char *lines[] = {
3697     "%CNXMAN,  Lost connection to system #\n"
3698     "%SHADOW-I-VOLPROC, DSA0: shadow master has changed.  "
3699     "Dump file WILL be written if system crashes.\n"
3700     "\n",
3701     "",
3702
3703     "%CNXMAN,  Quorum lost, blocking activity\n"
3704     "%CNXMAN,  Timed-out lost connection to system #\n"
3705     "%CNXMAN,  Timed-out lost connection to system #\n"
3706     "%CNXMAN,  Timed-out lost connection to system #\n"
3707     "%CNXMAN,  Proposing reconfiguration of the VMScluster\n",
3708     "",
3709
3710     "%CNXMAN,  Removed from VMScluster system #\n"
3711     "%CNXMAN,  Removed from VMScluster system #\n"
3712     "%CNXMAN,  Removed from VMScluster system #\n"
3713     "%CNXMAN,  Completing VMScluster state transition\n",
3714
3715     "\n"
3716     "**** OpenVMS (TM) Alpha Operating system V7.3-1   - BUGCHECK ****\n"
3717     "\n"
3718     "** Bugcheck code = 000005DC: CLUEXIT, Node voluntarily exiting "
3719     "VMScluster\n"
3720     "** Crash CPU: 00    Primary CPU: 00    Active CPUs: 00000001\n"
3721     "** Current Process = NULL\n"
3722     "** Current PSB ID = 00000001\n"
3723     "** Image Name =\n"
3724     "\n"
3725     "** Dumping error log buffers to HBVS unit 0\n"
3726     "**** Unable to dump error log buffers to remaining shadow set members\n"
3727     "** Error log buffers not dumped to HBVS unit 200\n"
3728     "\n"
3729     "** Dumping memory to HBVS unit 0\n"
3730     "**** Starting compressed selective memory dump at #...\n",
3731
3732     "...",
3733
3734     "\n"
3735     "**** Memory dump complete - not all processes or global pages saved\n",
3736
3737     "\n"
3738     "halted CPU 0\n",
3739     "",
3740
3741     "\n"
3742     "halt code = 5\n"
3743     "HALT instruction executed\n"
3744     "PC = ffffffff800c3884\n",
3745
3746     "\n"
3747     "CPU 0 booting\n",
3748
3749     "\n"
3750     "resetting all I/O buses\n"
3751     "\n"
3752     "\n"
3753     };
3754   char *args[8];
3755   int ids[3];
3756
3757   bst->scroll_p = True;
3758   bst->wrap_p = True;
3759   bst->left_margin = bst->right_margin = 10;
3760   bst->top_margin = bst->bottom_margin = 10;
3761
3762   sysname = "VMS001";
3763 # ifdef HAVE_UNAME
3764   {
3765     if (uname (&uts) >= 0)
3766       sysname = uts.nodename;
3767     s = strchr (sysname, '.');
3768     if (s) *s = 0;
3769   }
3770 # endif /* !HAVE_UNAME */
3771
3772   args[0] = malloc (strlen(sysname) + 7);
3773   strcpy (args[0], sysname);
3774   args[0][5] = 0;
3775
3776   /* Pick three numbers, 1-9, no overlaps. */
3777   ids[0] = 1 + (random() % 9);
3778   do { ids[1] = 1 + (random() % 9); } while (ids[1]==ids[0]);
3779   do { ids[2] = 1 + (random() % 9); } while (ids[2]==ids[0] || ids[2]==ids[1]);
3780
3781   i = strlen(args[0])-1;
3782   if (i < 6) i++;
3783   args[0][i] = '0' + ids[0];
3784   args[0][i+1] = 0;
3785
3786   for (s = args[0]; *s; s++)
3787     if (isalpha(*s)) *s = toupper (*s);
3788
3789   args[1] = strdup (args[0]);
3790   args[2] = strdup (args[0]); args[2][i] = '0' + ids[1];
3791   args[3] = strdup (args[0]); args[3][i] = '0' + ids[2];
3792
3793   args[4] = strdup (args[1]);
3794   args[5] = strdup (args[2]);
3795   args[6] = strdup (args[3]);
3796
3797   {
3798     time_t t = time ((time_t *) 0);
3799     struct tm *tm = localtime (&t);
3800     args[7] = malloc (30);
3801     strftime (args[7], 29, "%d-%b-%Y %H:%M", tm);
3802     for (s = args[7]; *s; s++)
3803       if (isalpha(*s)) *s = toupper (*s);
3804   }
3805
3806   arg_count = 0;
3807   for (i = 0; i < countof(lines); i++)
3808     {
3809       const char *fmt = lines[i];
3810       if (! strcmp (fmt, "..."))
3811         {
3812           int steps = 180 + (random() % 60);
3813           while (--steps >= 0)
3814             {
3815               BSOD_TEXT (bst, LEFT, ".");
3816               BSOD_PAUSE (bst, dot_delay);
3817             }
3818         }
3819       else
3820         {
3821           char *fmt2 = malloc (strlen (fmt) * 2 + 1);
3822           for (s = (char *) fmt, s1 = fmt2; *s; s++)
3823             {
3824               if (*s == '#')
3825                 {
3826                   strcpy (s1, args[arg_count++]);
3827                   s1 += strlen(s1);
3828                 }
3829               else
3830                 *s1++ = *s;
3831             }
3832           *s1 = 0;
3833           BSOD_CHAR_DELAY (bst, char_delay);
3834           BSOD_TEXT (bst, LEFT, fmt2);
3835           free (fmt2);
3836           BSOD_CHAR_DELAY (bst, 0);
3837           BSOD_PAUSE (bst, chunk_delay);
3838         }
3839     }
3840
3841   for (i = 0; i < countof (args); i++)
3842     free (args[i]);
3843
3844   XClearWindow(dpy, window);
3845   return bst;
3846 }
3847
3848
3849 /* HVX (formerly GCOS6) and TPS6 crash
3850    by Brian Garratt <brian-m.garratt@bull.co.uk>
3851
3852    GCOS6 is a Unix-like operating system developed by Honeywell in the
3853    1970s in collaboration with MIT and AT&T (who called their version
3854    UNIX).  Both are very much like MULTICS which Honeywell got from GE.
3855
3856    HVX ("High-performance Virtual System on Unix") is an AIX application
3857    which emulates GCOS6 hardware on RS6000-like machines.
3858  */
3859 static struct bsod_state *
3860 hvx (Display *dpy, Window window)
3861 {
3862   struct bsod_state *bst = make_bsod_state (dpy, window, "hvx", "HVX");
3863
3864   bst->scroll_p = True;
3865   bst->wrap_p = True;
3866   bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
3867     - bst->font->ascent;
3868
3869   BSOD_CHAR_DELAY (bst, 10000);
3870   BSOD_TEXT (bst, LEFT,
3871      "(TP) Trap no E   Effective address 00000000   Instruction D7DE\n"
3872      "(TP)  Registers :\n"
3873      "(TP)  B1 -> B7  03801B02  00000000  03880D45  038BABDB  0388AFFD"
3874      "  0389B3F8  03972317\n"
3875      "(TP)  R1 -> R7  0001  0007  F10F  090F  0020  0106  0272\n"
3876      "(TP)  P I Z M1  0388A18B  3232  0000 FF00\n"
3877      "(TP) Program counter is at offset 0028 from string YTPAD\n"
3878      "(TP) User id of task which trapped is LT 626\n"
3879      "(TP)?\n"
3880      );
3881   BSOD_PAUSE (bst, 1000000);
3882
3883   BSOD_CHAR_DELAY (bst, 100000);
3884   BSOD_TEXT (bst, LEFT, " TP CLOSE ALL");
3885
3886   BSOD_CHAR_DELAY (bst, 10000);
3887   BSOD_TEXT (bst, LEFT, "\n(TP)?\n");
3888   BSOD_PAUSE (bst, 1000000);
3889
3890   BSOD_CHAR_DELAY (bst, 100000);
3891   BSOD_TEXT (bst, LEFT, " TP ABORT -LT ALL");
3892
3893   BSOD_CHAR_DELAY (bst, 10000);
3894   BSOD_TEXT (bst, LEFT, "\n(TP)?\n");
3895   BSOD_PAUSE (bst, 1000000);
3896
3897   BSOD_CHAR_DELAY (bst, 100000);
3898   BSOD_TEXT (bst, LEFT, "  TP STOP KILL");
3899
3900   BSOD_CHAR_DELAY (bst, 10000);
3901   BSOD_TEXT (bst, LEFT,
3902      "\n"
3903      "(TP)?\n"
3904      "Core dumps initiated for selected HVX processes ...\n"
3905      "Core dumps complete.\n"
3906      "Fri Jul 19 15:53:09 2002\n"
3907      "Live registers for cp 0:\n"
3908      " P    =     7de3  IW=0000     I=32    CI=30000000   S=80006013"
3909      "   IV=aa0      Level=13\n"
3910      " R1-7 =       1f      913       13        4        8        0        0\n"
3911      " B1-7 =   64e71b      a93      50e   64e73c     6c2c     7000      b54\n"
3912      "Memory dump starting to file /var/hvx/dp01/diag/Level2 ...\n"
3913      "Memory dump complete.\n"
3914     );
3915
3916   XClearWindow(dpy, window);
3917   return bst;
3918 }
3919
3920
3921 /* HPUX panic, by Tobias Klausmann <klausman@schwarzvogel.de>
3922  */
3923 static struct bsod_state *
3924 hpux (Display *dpy, Window window)
3925 {
3926   struct bsod_state *bst = make_bsod_state (dpy, window, "hpux", "HPUX");
3927   const char *sysname;
3928   char buf[2048];
3929 # ifdef HAVE_UNAME
3930   struct utsname uts;
3931 # endif /* UNAME */
3932
3933   bst->scroll_p = True;
3934   bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
3935     - bst->font->ascent;
3936
3937   sysname = "HPUX";
3938 # ifdef HAVE_UNAME
3939   {
3940     char *s;
3941     if (uname (&uts) >= 0)
3942       sysname = uts.nodename;
3943     s = strchr (sysname, '.');
3944     if (s) *s = 0;
3945   }
3946 # endif /* !HAVE_UNAME */
3947
3948   BSOD_TEXT (bst, LEFT,
3949              "                                                       "
3950              "                                                       "
3951              "                                                       \n");
3952   sprintf (buf, "%.100s [HP Release B.11.00] (see /etc/issue)\n", sysname);
3953   BSOD_TEXT (bst, LEFT, buf);
3954   BSOD_PAUSE (bst, 1000000);
3955   BSOD_TEXT (bst, LEFT,
3956    "Console Login:\n"
3957    "\n"
3958    "     ******* Unexpected HPMC/TOC. Processor HPA FFFFFFFF'"
3959    "FFFA0000 *******\n"
3960    "                              GENERAL REGISTERS:\n"
3961    "r00/03 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
3962    "006C76C0\n"
3963    "r04/07 00000000'00000001 00000000'0126E328 00000000'00000000 00000000'"
3964    "0122B640\n"
3965    "r08/11 00000000'00000000 00000000'0198CFC0 00000000'000476FE 00000000'"
3966    "00000001\n"
3967    "r12/15 00000000'40013EE8 00000000'08000080 00000000'4002530C 00000000'"
3968    "4002530C\n"
3969    "r16/19 00000000'7F7F2A00 00000000'00000001 00000000'00000000 00000000'"
3970    "00000000\n"
3971    "r20/23 00000000'006C8048 00000000'00000001 00000000'00000000 00000000'"
3972    "00000000\n"
3973    "r24/27 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
3974    "00744378\n"
3975    "r28/31 00000000'00000000 00000000'007DD628 00000000'0199F2B0 00000000'"
3976    "00000000\n"
3977    "                              CONTROL REGISTERS:\n"
3978    "sr0/3  00000000'0F3B4000 00000000'0C2A2000 00000000'016FF800 00000000'"
3979    "00000000\n"
3980    "sr4/7  00000000'00000000 00000000'016FF800 00000000'0DBF1400 00000000'"
3981    "00000000\n"
3982    "pcq =  00000000'00000000.00000000'00104950 00000000'00000000.00000000'"
3983    "00104A14\n"
3984    "isr =  00000000'10240006 ior = 00000000'67D9E220 iir = 08000240 rctr = "
3985    "7FF10BB6\n"
3986    "\n"
3987    "pid reg cr8/cr9    00007700'0000B3A9 00000000'0000C5D8\n"
3988    "pid reg cr12/cr13  00000000'00000000 00000000'00000000\n"
3989    "ipsw = 000000FF'080CFF1F iva = 00000000'0002C000 sar = 3A ccr = C0\n"
3990    "tr0/3  00000000'006C76C0 00000000'00000001 00000000'00000000 00000000'"
3991    "7F7CE000\n"
3992    "tr4/7  00000000'03790000 0000000C'4FB68340 00000000'C07EE13F 00000000'"
3993    "0199F2B0\n"
3994    "eiem = FFFFFFF0'FFFFFFFF eirr = 80000000'00000000 itmr = 0000000C'"
3995    "4FD8EDE1\n"
3996    "cr1/4  00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
3997    "00000000\n"
3998    "cr5/7  00000000'00000000 00000000'00000000 00000000'"
3999    "00000000\n"
4000    "                           MACHINE CHECK PARAMETERS:\n"
4001    "Check Type = 00000000 CPU STATE = 9E000001 Cache Check = 00000000\n"
4002    "TLB Check = 00000000 Bus Check = 00000000 PIM State = ? SIU "
4003    "Status = ????????\n"
4004    "Assists = 00000000 Processor = 00000000\n"
4005    "Slave Addr = 00000000'00000000 Master Addr = 00000000'00000000\n"
4006    "\n"
4007    "\n"
4008    "TOC,    pcsq.pcoq = 0'0.0'104950   , isr.ior = 0'10240006.0'67d9e220\n"
4009    "@(#)B2352B/9245XB HP-UX (B.11.00) #1: Wed Nov  5 22:38:19 PST 1997\n"
4010    "Transfer of control: (display==0xd904, flags==0x0)\n"
4011    "\n"
4012    "\n"
4013    "\n"
4014    "*** A system crash has occurred.  (See the above messages for details.)\n"
4015    "*** The system is now preparing to dump physical memory to disk, for use\n"
4016    "*** in debugging the crash.\n"
4017    "\n"
4018    "*** The dump will be a SELECTIVE dump:  40 of 256 megabytes.\n"
4019    "*** To change this dump type, press any key within 10 seconds.\n"
4020    "*** Proceeding with selective dump.\n"
4021    "\n"
4022    "*** The dump may be aborted at any time by pressing ESC.\n");
4023
4024   {
4025     int i;
4026     int steps = 11;
4027     int size = 40;
4028     for (i = 0; i <= steps; i++)
4029       {
4030         if (i > steps) i = steps;
4031         sprintf (buf,
4032                "*** Dumping: %3d%% complete (%d of 40 MB) (device 64:0x2)\r",
4033                  i * 100 / steps,
4034                  i * size / steps);
4035         BSOD_TEXT (bst, LEFT, buf);
4036         BSOD_PAUSE (bst, 1500000);
4037       }
4038   }
4039
4040   BSOD_TEXT (bst, LEFT, "\n*** System rebooting.\n");
4041
4042   XClearWindow(dpy, window);
4043   return bst;
4044 }
4045
4046
4047 /* IBM OS/390 aka MVS aka z/OS.
4048    Text from Dan Espen <dane@mk.telcordia.com>.
4049    Apparently this isn't actually a crash, just a random session...
4050    But who can tell.
4051  */
4052 static struct bsod_state *
4053 os390 (Display *dpy, Window window)
4054 {
4055   struct bsod_state *bst = make_bsod_state (dpy, window, "os390", "OS390");
4056
4057   bst->scroll_p = True;
4058   bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
4059     - bst->font->ascent;
4060
4061   BSOD_LINE_DELAY (bst, 100000);
4062   BSOD_TEXT (bst, LEFT,
4063    "\n*** System rebooting.\n"
4064    "* ISPF Subtask abend *\n"
4065    "SPF      ENDED DUE TO ERROR+\n"
4066    "READY\n"
4067    "\n"
4068    "IEA995I SYMPTOM DUMP OUTPUT\n"
4069    "  USER COMPLETION CODE=0222\n"
4070    " TIME=23.00.51  SEQ=03210  CPU=0000  ASID=00AE\n"
4071    " PSW AT TIME OF ERROR  078D1000   859DAF18  ILC 2  INTC 0D\n"
4072    "   NO ACTIVE MODULE FOUND\n"
4073    "   NAME=UNKNOWN\n"
4074    "   DATA AT PSW  059DAF12 - 00181610  0A0D9180  70644710\n"
4075    "   AR/GR 0: 00000000/80000000   1: 00000000/800000DE\n"
4076    "         2: 00000000/196504DC   3: 00000000/00037A78\n"
4077    "         4: 00000000/00037B78   5: 00000000/0003351C\n"
4078    "         6: 00000000/0000F0AD   7: 00000000/00012000\n"
4079    "         8: 00000000/059DAF10   9: 00000000/0002D098\n"
4080    "         A: 00000000/059D9F10   B: 00000000/059D8F10\n"
4081    "         C: 00000000/859D7F10   D: 00000000/00032D60\n"
4082    "         E: 00000000/00033005   F: 01000002/00000041\n"
4083    " END OF SYMPTOM DUMP\n"
4084    "ISPS014 - ** Logical screen request failed - abend 0000DE **\n"
4085    "ISPS015 - ** Contact your system programmer or dialog developer.**\n"
4086    "*** ISPF Main task abend ***\n"
4087    "IEA995I SYMPTOM DUMP OUTPUT\n"
4088    "  USER COMPLETION CODE=0222\n"
4089    " TIME=23.00.52  SEQ=03211  CPU=0000  ASID=00AE\n"
4090    " PSW AT TIME OF ERROR  078D1000   8585713C  ILC 2  INTC 0D\n"
4091    "   ACTIVE LOAD MODULE           ADDRESS=05855000  OFFSET=0000213C\n"
4092    "   NAME=ISPMAIN\n"
4093    "   DATA AT PSW  05857136 - 00181610  0A0D9180  D3304770\n"
4094    "   GR 0: 80000000   1: 800000DE\n"
4095    "      2: 00015260   3: 00000038\n"
4096    "      4: 00012508   5: 00000000\n"
4097    "      6: 000173AC   7: FFFFFFF8\n"
4098    "      8: 05858000   9: 00012CA0\n"
4099    "      A: 05857000   B: 05856000\n"
4100    "      C: 85855000   D: 00017020\n"
4101    "      E: 85857104   F: 00000000\n"
4102    " END OF SYMPTOM DUMP\n"
4103    "READY\n"
4104    "***");
4105   BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999);
4106
4107   XClearWindow(dpy, window);
4108   return bst;
4109 }
4110
4111
4112 /* Compaq Tru64 Unix panic, by jwz as described by
4113    Tobias Klausmann <klausman@schwarzvogel.de>
4114  */
4115 static struct bsod_state *
4116 tru64 (Display *dpy, Window window)
4117 {
4118   struct bsod_state *bst = make_bsod_state (dpy, window, "tru64", "Tru64");
4119   const char *sysname;
4120   char buf[2048];
4121 # ifdef HAVE_UNAME
4122   struct utsname uts;
4123 #endif /* UNAME */
4124
4125   bst->scroll_p = True;
4126   bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
4127     - bst->font->ascent;
4128
4129   sysname = "127.0.0.1";
4130 # ifdef HAVE_UNAME
4131   {
4132     if (uname (&uts) >= 0)
4133       sysname = uts.nodename;
4134   }
4135 # endif /* !HAVE_UNAME */
4136
4137   sprintf (buf,
4138            "Compaq Tru64 UNIX V5.1B (Rev. 2650) (%.100s) console\n"
4139            "\n"
4140            "login: ",
4141            sysname);
4142   BSOD_TEXT (bst, LEFT, buf);
4143   BSOD_PAUSE (bst, 6000000);
4144
4145   BSOD_TEXT (bst, LEFT,
4146     "panic (cpu 0): trap: illegal instruction\n"
4147     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
4148     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
4149     "                                                                   \n"
4150     "DUMP: blocks available:  1571600\n"
4151     "DUMP: blocks wanted:      100802 (partial compressed dump) [OKAY]\n"
4152     "DUMP: Device     Disk Blocks Available\n"
4153     "DUMP: ------     ---------------------\n"
4154     "DUMP: 0x1300023  1182795 - 1571597 (of 1571598) [primary swap]\n"
4155     "DUMP.prom: Open: dev 0x5100041, block 2102016: SCSI 0 11 0 2 200 0 0\n"
4156     "DUMP: Writing header... [1024 bytes at dev 0x1300023, block 1571598]\n"
4157     "DUMP: Writing data");
4158
4159   {
4160     int i;
4161     int steps = 4 + (random() % 8);
4162     BSOD_CHAR_DELAY (bst, 1000000);
4163     for (i = 0; i < steps; i++)
4164       BSOD_TEXT (bst, LEFT, ".");
4165     BSOD_CHAR_DELAY (bst, 0);
4166     sprintf (buf, "[%dMB]\n", steps);
4167     BSOD_TEXT (bst, LEFT, buf);
4168   }
4169
4170   BSOD_TEXT (bst, LEFT,
4171     "DUMP: Writing header... [1024 bytes at dev 0x1300023, block 1571598]\n"
4172     "DUMP: crash dump complete.\n"
4173     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
4174     "                                                                   \n"
4175     "DUMP: second crash dump skipped: 'dump_savecnt' enforced.\n");
4176   BSOD_PAUSE (bst, 4000000);
4177
4178   BSOD_TEXT (bst, LEFT,
4179     "\n"
4180     "halted CPU 0\n"
4181     "\n"
4182     "halt code = 5\n"
4183     "HALT instruction executed\n"
4184     "PC = fffffc00005863b0\n");
4185   BSOD_PAUSE (bst, 3000000);
4186
4187   BSOD_TEXT (bst, LEFT,
4188     "\n"
4189     "CPU 0 booting\n"
4190     "\n"
4191     "\n"
4192     "\n");
4193
4194   XClearWindow(dpy, window);
4195   return bst;
4196 }
4197
4198
4199 /* MS-DOS, by jwz
4200  */
4201 static struct bsod_state *
4202 msdos (Display *dpy, Window window)
4203 {
4204   struct bsod_state *bst = make_bsod_state (dpy, window, "msdos", "MSDOS");
4205
4206   BSOD_CHAR_DELAY (bst, 10000);
4207   BSOD_TEXT (bst, LEFT, "C:\\WINDOWS>");
4208   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 8);
4209
4210   BSOD_CHAR_DELAY (bst, 200000);
4211   BSOD_TEXT (bst, LEFT, "dir a:");
4212   BSOD_PAUSE (bst, 1000000);
4213
4214   BSOD_CHAR_DELAY (bst, 10000);
4215   BSOD_TEXT (bst, LEFT, "\nNot ready reading drive A\nAbort, Retry, Fail?");
4216
4217   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 10);
4218   BSOD_CHAR_DELAY (bst, 200000);
4219   BSOD_TEXT (bst, LEFT, "f");
4220   BSOD_PAUSE (bst, 1000000);
4221
4222   BSOD_CHAR_DELAY (bst, 10000);
4223   BSOD_TEXT (bst, LEFT,
4224              "\n\n\nNot ready reading drive A\nAbort, Retry, Fail?");
4225
4226   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 10);
4227   BSOD_CHAR_DELAY (bst, 200000);
4228   BSOD_TEXT (bst, LEFT, "f");
4229   BSOD_PAUSE (bst, 1000000);
4230
4231   BSOD_CHAR_DELAY (bst, 10000);
4232   BSOD_TEXT (bst, LEFT, "\nVolume in drive A has no label\n\n"
4233                   "Not ready reading drive A\nAbort, Retry, Fail?");
4234
4235   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 12);
4236   BSOD_CHAR_DELAY (bst, 200000);
4237   BSOD_TEXT (bst, LEFT, "a");
4238   BSOD_PAUSE (bst, 1000000);
4239
4240   BSOD_CHAR_DELAY (bst, 10000);
4241   BSOD_TEXT (bst, LEFT, "\n\nC:\\WINDOWS>");
4242
4243   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 999999);
4244
4245   XClearWindow(dpy, window);
4246   return bst;
4247 }
4248
4249
4250 /* nvidia, by jwz.
4251  *
4252  * This is what happens if an Nvidia card goes into some crazy text mode.
4253  * Most often seen on the second screen of a dual-head system when the
4254  * proper driver isn't loaded.
4255  */
4256 typedef struct { int fg; int bg; int bit; Bool blink; } nvcell;
4257
4258 static void
4259 nvspatter (nvcell *grid, int rows, int cols, int ncolors, int nbits,
4260            Bool fill_p)
4261 {
4262   int max = rows * cols;
4263   int from = fill_p ?   0 : random() % (max - 1);
4264   int len  = fill_p ? max : random() % (cols * 4);
4265   int to = from + len;
4266   int i;
4267   Bool noisy = ((random() % 4) == 0);
4268   Bool diag = (noisy || fill_p) ? 0 : ((random() % 4) == 0);
4269
4270   int fg = random() % ncolors;
4271   int bg = random() % ncolors;
4272   int blink = ((random() % 4) == 0);
4273   int bit = (random() % nbits);
4274
4275   if (to > max) to = max;
4276
4277   if (diag)
4278     {
4279       int src = random() % (rows * cols);
4280       int len2 = (cols / 2) - (random() % 5);
4281       int j = src;
4282       for (i = from; i < to; i++, j++)
4283         {
4284           if (j > src + len2 || j >= max)
4285             j = src;
4286           if (i >= max) abort();
4287           if (j >= max) abort();
4288           grid[j] = grid[i];
4289         }
4290     }
4291   else
4292     for (i = from; i < to; i++)
4293       {
4294         nvcell *cell = &grid[i];
4295         cell->fg = fg;
4296         cell->bg = bg;
4297         cell->bit = bit;
4298         cell->blink = blink;
4299
4300         if (noisy)
4301           {
4302             fg = random() % ncolors;
4303             bg = random() % ncolors;
4304             blink = ((random() % 8) == 0);
4305           }
4306       }
4307 }
4308
4309 typedef struct {
4310   struct bsod_state *bst;
4311   GC gc1;
4312   Pixmap bits[5];
4313   int rows, cols;
4314   int cellw, cellh;
4315   nvcell *grid;
4316   int ncolors;
4317   unsigned long colors[256];
4318   int tick;
4319 } nvstate;
4320
4321
4322 static void
4323 nvidia_free (struct bsod_state *bst)
4324 {
4325   nvstate *nvs = (nvstate *) bst->closure;
4326   int i;
4327   XFreeColors (bst->dpy, bst->xgwa.colormap, nvs->colors, nvs->ncolors, 0);
4328   for (i = 0; i < countof(nvs->bits); i++)
4329     XFreePixmap (bst->dpy, nvs->bits[i]);
4330   XFreeGC (bst->dpy, nvs->gc1);
4331   free (nvs->grid);
4332   free (nvs);
4333 }
4334
4335 static int
4336 nvidia_draw (struct bsod_state *bst)
4337 {
4338   nvstate *nvs = (nvstate *) bst->closure;
4339   int x, y;
4340
4341   for (y = 0; y < nvs->rows; y++)
4342     for (x = 0; x < nvs->cols; x++)
4343       {
4344         nvcell *cell = &nvs->grid[y * nvs->cols + x];
4345         unsigned long fg = nvs->colors[cell->fg];
4346         unsigned long bg = nvs->colors[cell->bg];
4347         Bool flip = cell->blink && (nvs->tick & 1);
4348         XSetForeground (bst->dpy, bst->gc, flip ? fg : bg);
4349         XSetBackground (bst->dpy, bst->gc, flip ? bg : fg);
4350         XCopyPlane (bst->dpy, nvs->bits[cell->bit], bst->window, bst->gc,
4351                     0, 0, nvs->cellw, nvs->cellh,
4352                     x * nvs->cellw, y * nvs->cellh, 1L);
4353       }
4354
4355   nvs->tick++;
4356   if ((random() % 5) == 0)    /* change the display */
4357     nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors,
4358                countof(nvs->bits), False);
4359
4360   return 250000;
4361 }
4362
4363
4364 static struct bsod_state *
4365 nvidia (Display *dpy, Window window)
4366 {
4367   struct bsod_state *bst = make_bsod_state (dpy, window, "nvidia", "nVidia");
4368   nvstate *nvs = (nvstate *) calloc (1, sizeof (*nvs));
4369
4370   XGCValues gcv;
4371   int i;
4372
4373   nvs->bst = bst;
4374   bst->closure = nvs;
4375   bst->draw_cb = nvidia_draw;
4376   bst->free_cb = nvidia_free;
4377
4378   nvs->cols = 80;
4379   nvs->rows = 25;
4380   nvs->cellw = bst->xgwa.width  / nvs->cols;
4381   nvs->cellh = bst->xgwa.height / nvs->rows;
4382   if (nvs->cellw < 8 || nvs->cellh < 18)
4383     nvs->cellw = 8, nvs->cellh = 18;
4384   nvs->cols = (bst->xgwa.width  / nvs->cellw) + 1;
4385   nvs->rows = (bst->xgwa.height / nvs->cellh) + 1;
4386
4387   nvs->grid = (nvcell *) calloc (sizeof(*nvs->grid), nvs->rows * nvs->cols);
4388
4389   /* Allocate colors
4390    */
4391   nvs->ncolors = 16;
4392   for (i = 0; i < nvs->ncolors; i++)
4393     {
4394       XColor c;
4395       c.red   = random() & 0xFFFF;
4396       c.green = random() & 0xFFFF;
4397       c.blue  = random() & 0xFFFF;
4398       c.flags = DoRed|DoGreen|DoBlue;
4399       XAllocColor (dpy, bst->xgwa.colormap, &c);
4400       nvs->colors[i] = c.pixel;
4401     }
4402
4403   /* Construct corrupted character bitmaps
4404    */
4405   for (i = 0; i < countof(nvs->bits); i++)
4406     {
4407       int j;
4408
4409       nvs->bits[i] = XCreatePixmap (dpy, window, nvs->cellw, nvs->cellh, 1);
4410       if (!nvs->gc1) nvs->gc1 = XCreateGC (dpy, nvs->bits[i], 0, &gcv);
4411
4412       XSetForeground (dpy, nvs->gc1, 0);
4413       XFillRectangle (dpy, nvs->bits[i], nvs->gc1, 0, 0,
4414                       nvs->cellw, nvs->cellh);
4415       XSetForeground (dpy, nvs->gc1, 1);
4416
4417       if ((random() % 40) != 0)
4418         for (j = 0; j < ((nvs->cellw * nvs->cellh) / 16); j++)
4419           XFillRectangle (dpy, nvs->bits[i], nvs->gc1,
4420                           (random() % (nvs->cellw-2)) & ~1,
4421                           (random() % (nvs->cellh-2)) & ~1,
4422                           2, 2);
4423     }
4424
4425   /* Randomize the grid
4426    */
4427   nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors,
4428              countof(nvs->bits), True);
4429   for (i = 0; i < 20; i++)
4430     nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors,
4431                countof(nvs->bits), False);
4432
4433   return bst;
4434 }
4435
4436
4437 /*
4438  * Simulate various Apple ][ crashes. The memory map encouraged many programs
4439  * to use the primary hi-res video page for various storage, and the secondary
4440  * hi-res page for active display. When it crashed into Applesoft or the
4441  * monitor, it would revert to the primary page and you'd see memory garbage on
4442  * the screen. Also, it was common for copy-protected games to use the primary
4443  * text page for important code, because that made it really hard to
4444  * reverse-engineer them. The result often looked like what this generates.
4445  *
4446  * The Apple ][ logic and video hardware is in apple2.c. The TV is emulated by
4447  * analogtv.c for maximum realism
4448  *
4449  * Trevor Blackwell <tlb@tlb.org>
4450  */
4451
4452 static const char * const apple2_basic_errors[]={
4453   "BREAK",
4454   "NEXT WITHOUT FOR",
4455   "SYNTAX ERROR",
4456   "RETURN WITHOUT GOSUB",
4457   "ILLEGAL QUANTITY",
4458   "OVERFLOW",
4459   "OUT OF MEMORY",
4460   "BAD SUBSCRIPT ERROR",
4461   "DIVISION BY ZERO",
4462   "STRING TOO LONG",
4463   "FORMULA TOO COMPLEX",
4464   "UNDEF'D FUNCTION",
4465   "OUT OF DATA"
4466 #if 0
4467   ,
4468   "DEFAULT ARGUMENTS ARE NOT ALLOWED IN DECLARATION OF FRIEND "
4469   "TEMPLATE SPECIALIZATION"
4470 #endif
4471
4472 };
4473 static const char * const apple2_dos_errors[]={
4474   "VOLUME MISMATCH",
4475   "I/O ERROR",
4476   "DISK FULL",
4477   "NO BUFFERS AVAILABLE",
4478   "PROGRAM TOO LARGE",
4479 };
4480
4481 static void a2controller_crash(apple2_sim_t *sim, int *stepno,
4482                                double *next_actiontime)
4483 {
4484   apple2_state_t *st=sim->st;
4485   char *s;
4486   int i;
4487
4488   struct mydata {
4489     int fillptr;
4490     int fillbyte;
4491   } *mine;
4492
4493   if (!sim->controller_data)
4494     sim->controller_data = calloc(sizeof(struct mydata),1);
4495   mine=(struct mydata *) sim->controller_data;
4496
4497   switch(*stepno) {
4498   case 0:
4499
4500     a2_init_memory_active(sim);
4501     sim->dec->powerup = 1000.0;
4502
4503     if (random()%3==0) {
4504       st->gr_mode=0;
4505       *next_actiontime+=0.4;
4506       *stepno=100;
4507     }
4508     else if (random()%4==0) {
4509       st->gr_mode=A2_GR_LORES;
4510       if (random()%3==0) st->gr_mode |= A2_GR_FULL;
4511       *next_actiontime+=0.4;
4512       *stepno=100;
4513     }
4514     else if (random()%2==0) {
4515       st->gr_mode=A2_GR_HIRES;
4516       *stepno=300;
4517     }
4518     else {
4519       st->gr_mode=A2_GR_HIRES;
4520       *next_actiontime+=0.4;
4521       *stepno=100;
4522     }
4523     break;
4524
4525   case 100:
4526     /* An illegal instruction or a reset caused it to drop into the
4527        assembly language monitor, where you could disassemble code & view
4528        data in hex. */
4529     if (random()%3==0) {
4530       char ibytes[128];
4531       char itext[128];
4532       int addr=0xd000+random()%0x3000;
4533       sprintf(ibytes,
4534               "%02X",random()%0xff);
4535       sprintf(itext,
4536               "???");
4537       sprintf(sim->printing_buf,
4538               "\n\n"
4539               "%04X: %-15s %s\n"
4540               " A=%02X X=%02X Y=%02X S=%02X F=%02X\n"
4541               "*",
4542               addr,ibytes,itext,
4543               random()%0xff, random()%0xff,
4544               random()%0xff, random()%0xff,
4545               random()%0xff);
4546       sim->printing=sim->printing_buf;
4547       a2_goto(st,23,1);
4548       if (st->gr_mode) {
4549         *stepno=180;
4550       } else {
4551         *stepno=200;
4552       }
4553       sim->prompt='*';
4554       *next_actiontime += 2.0 + (random()%1000)*0.0002;
4555     }
4556     else {
4557       /* Lots of programs had at least their main functionality in
4558          Applesoft Basic, which had a lot of limits (memory, string
4559          length, etc) and would sometimes crash unexpectedly. */
4560       sprintf(sim->printing_buf,
4561               "\n"
4562               "\n"
4563               "\n"
4564               "?%s IN %d\n"
4565               "\001]",
4566               apple2_basic_errors[random() %
4567                                   (sizeof(apple2_basic_errors)
4568                                    /sizeof(char *))],
4569               (1000*(random()%(random()%59+1)) +
4570                100*(random()%(random()%9+1)) +
4571                5*(random()%(random()%199+1)) +
4572                1*(random()%(random()%(random()%2+1)+1))));
4573       sim->printing=sim->printing_buf;
4574       a2_goto(st,23,1);
4575       *stepno=110;
4576       sim->prompt=']';
4577       *next_actiontime += 2.0 + (random()%1000)*0.0002;
4578     }
4579     break;
4580
4581   case 110:
4582     if (random()%3==0) {
4583       /* This was how you reset the Basic interpreter. The sort of
4584          incantation you'd have on a little piece of paper taped to the
4585          side of your machine */
4586       sim->typing="CALL -1370";
4587       *stepno=120;
4588     }
4589     else if (random()%2==0) {
4590       sim->typing="CATALOG\n";
4591       *stepno=170;
4592     }
4593     else {
4594       *next_actiontime+=1.0;
4595       *stepno=999;
4596     }
4597     break;
4598
4599   case 120:
4600     *stepno=130;
4601     *next_actiontime += 0.5;
4602     break;
4603
4604   case 130:
4605     st->gr_mode=0;
4606     a2_cls(st);
4607     a2_goto(st,0,16);
4608     for (s="APPLE ]["; *s; s++) a2_printc(st,*s);
4609     a2_goto(st,23,0);
4610     a2_printc(st,']');
4611     *next_actiontime+=1.0;
4612     *stepno=999;
4613     break;
4614
4615   case 170:
4616     if (random()%50==0) {
4617       sprintf(sim->printing_buf,
4618               "\nDISK VOLUME 254\n\n"
4619               " A 002 HELLO\n"
4620               "\n"
4621               "]");
4622       sim->printing=sim->printing_buf;
4623     }
4624     else {
4625       sprintf(sim->printing_buf,"\n?%s\n]",
4626               apple2_dos_errors[random()%
4627                                 (sizeof(apple2_dos_errors) /
4628                                  sizeof(char *))]);
4629       sim->printing=sim->printing_buf;
4630     }
4631     *stepno=999;
4632     *next_actiontime+=1.0;
4633     break;
4634
4635   case 180:
4636     if (random()%2==0) {
4637       /* This was how you went back to text mode in the monitor */
4638       sim->typing="FB4BG";
4639       *stepno=190;
4640     } else {
4641       *next_actiontime+=1.0;
4642       *stepno=999;
4643     }
4644     break;
4645
4646   case 190:
4647     st->gr_mode=0;
4648     a2_invalidate(st);
4649     a2_printc(st,'\n');
4650     a2_printc(st,'*');
4651     *stepno=200;
4652     *next_actiontime+=2.0;
4653     break;
4654
4655   case 200:
4656     /* This reset things into Basic */
4657     if (random()%2==0) {
4658       sim->typing="FAA6G";
4659       *stepno=120;
4660     }
4661     else {
4662       *stepno=999;
4663       *next_actiontime+=sim->delay;
4664     }
4665     break;
4666
4667   case 300:
4668     for (i=0; i<1500; i++) {
4669       a2_poke(st, mine->fillptr, mine->fillbyte);
4670       mine->fillptr++;
4671       mine->fillbyte = (mine->fillbyte+1)&0xff;
4672     }
4673     *next_actiontime += 0.08;
4674     /* When you hit c000, it changed video settings */
4675     if (mine->fillptr>=0xc000) {
4676       a2_invalidate(st);
4677       st->gr_mode=0;
4678     }
4679     /* And it seemed to reset around here, I dunno why */
4680     if (mine->fillptr>=0xcf00) *stepno=130;
4681     break;
4682
4683   case 999:
4684     break;
4685
4686   case A2CONTROLLER_FREE:
4687     free(mine);
4688     mine = 0;
4689     break;
4690   }
4691 }
4692
4693 static int
4694 a2_draw (struct bsod_state *bst)
4695 {
4696   apple2_sim_t *sim = (apple2_sim_t *) bst->closure;
4697   if (! sim) {
4698     sim = apple2_start (bst->dpy, bst->window, 9999999, a2controller_crash);
4699     bst->closure = sim;
4700   }
4701
4702   if (! apple2_one_frame (sim)) {
4703     bst->closure = 0;
4704   }
4705
4706   return 10000;
4707 }
4708
4709 static void
4710 a2_free (struct bsod_state *bst)
4711 {
4712   apple2_sim_t *sim = (apple2_sim_t *) bst->closure;
4713   if (sim) {
4714     sim->stepno = A2CONTROLLER_DONE;
4715     a2_draw (bst);              /* finish up */
4716     if (bst->closure) abort();  /* should have been freed by now */
4717   }
4718 }
4719
4720
4721 static struct bsod_state *
4722 apple2crash (Display *dpy, Window window)
4723 {
4724   struct bsod_state *bst = make_bsod_state (dpy, window, "apple2", "Apple2");
4725   bst->draw_cb = a2_draw;
4726   bst->free_cb = a2_free;
4727   return bst;
4728 }
4729
4730
4731 static void
4732 a2controller_ransomware(apple2_sim_t *sim, int *stepno,
4733                         double *next_actiontime)
4734 {
4735   apple2_state_t *st=sim->st;
4736
4737   struct mydata {
4738     const char *str;
4739     Bool bold_p;
4740   } *mine;
4741
4742   if (!sim->controller_data)
4743     sim->controller_data = calloc(sizeof(struct mydata),1);
4744   mine=(struct mydata *) sim->controller_data;
4745
4746   switch(*stepno) {
4747   case 0:
4748
4749     st->gr_mode |= A2_GR_FULL;
4750     a2_cls(st);
4751     a2_goto(st,0,16);
4752     a2_prints(st, "APPLE ][");
4753     a2_goto(st,2,0);
4754     *stepno = 10;
4755     *next_actiontime += 2;
4756     break;
4757
4758   case 10:
4759     a2_prints(st, "READY\n\n");
4760     *stepno = 11;
4761     *next_actiontime += 1;
4762     break;
4763
4764   case 11:
4765     a2_goto(st, 1, 0);
4766     *stepno = 12;
4767     mine->str =
4768       ("\n"
4769        " _____________________________________\n"
4770        "/                                     \\\n"
4771        "! OOPS YOUR FILES HAVE BEEN ENCRYPTED !\n"
4772        "!          ________________________   !\n"
4773        "!         !                        !  !\n"
4774        "!  [/--\\]   !  [ WHAT HAPPENED TO MY ] !  !\n"
4775        "!  [!]  [!]   !  [ COMPUTER? ]           !  !\n"
4776        "!  [!]  [!]   !                        !  !\n"
4777        "! [######]  !  [ CAN I RECOVER MY ]    !  !\n"
4778        "! [######]  !  [ FILES? ]              !  !\n"
4779        "! [######]  !                        !  !\n"
4780        "! [######]  !  [ HOW DO I PAY? ]       !  !\n"
4781        "!         !                        !  !\n"
4782        "!         !________________________!  !\n"
4783        "!                                     !\n"
4784        "!         BITCOIN ACCEPTED HERE       !\n"
4785        "\\_____________________________________/\n"
4786        "\n"
4787        "\n"
4788        "WAITING FOR BLOCKCHAIN..@\n"
4789        "\n"
4790        "PLEASE INSERT NEXT FLOPPY: "
4791        );
4792     break;
4793
4794   case 12:
4795     {
4796       char c = *mine->str;
4797       mine->str++;
4798
4799       if (c == 0)
4800         {
4801           *next_actiontime += 30;
4802           *stepno = 0;
4803         }
4804       else if (c == '[')
4805         mine->bold_p++;
4806       else if (c == ']')
4807         mine->bold_p--;
4808       else
4809         {
4810           if (c == '@')
4811             {
4812               c = '.';
4813               *next_actiontime += 2;
4814             }
4815
4816           if (mine->bold_p)
4817             c |= 0xC0;
4818           a2_printc_noscroll(st, c);
4819           if (c == '.')
4820             *next_actiontime += 1;
4821         }
4822     }
4823     break;
4824
4825   case A2CONTROLLER_FREE:
4826     return;
4827   }
4828 }
4829
4830
4831 static int
4832 a2_ransomware_draw (struct bsod_state *bst)
4833 {
4834   apple2_sim_t *sim = (apple2_sim_t *) bst->closure;
4835   if (! sim) {
4836     sim = apple2_start (bst->dpy, bst->window, 9999999,
4837                         a2controller_ransomware);
4838     bst->closure = sim;
4839   }
4840
4841   if (! apple2_one_frame (sim)) {
4842     bst->closure = 0;
4843   }
4844
4845   return 10000;
4846 }
4847
4848 static struct bsod_state *
4849 apple2ransomware (Display *dpy, Window window)
4850 {
4851   struct bsod_state *bst = make_bsod_state (dpy, window, "apple2", "Apple2");
4852   bst->draw_cb = a2_ransomware_draw;
4853   bst->free_cb = a2_free;
4854   return bst;
4855 }
4856
4857
4858
4859 /* A crash spotted on a cash machine circa 2006, by jwz.  I didn't note
4860    what model it was; probably a Tranax Mini-Bank 1000 or similar vintage.
4861  */
4862 static struct bsod_state *
4863 atm (Display *dpy, Window window)
4864 {
4865   struct bsod_state *bst = make_bsod_state (dpy, window, "atm", "ATM");
4866
4867   Pixmap pixmap = 0;
4868   int pix_w = atm_width;
4869   int pix_h = atm_height;
4870   int x, y, i = 0;
4871   float scale = 0.48;
4872
4873   XClearWindow (dpy, window);
4874
4875   pixmap = XCreatePixmapFromBitmapData (dpy, window, (char *) atm_bits,
4876                                         atm_width, atm_height,
4877                                         bst->fg, bst->bg, bst->xgwa.depth);
4878
4879   while (pix_w <= bst->xgwa.width  * scale &&
4880          pix_h <= bst->xgwa.height * scale)
4881     {
4882       pixmap = double_pixmap (dpy, bst->gc, bst->xgwa.visual, bst->xgwa.depth,
4883                               pixmap, pix_w, pix_h);
4884       pix_w *= 2;
4885       pix_h *= 2;
4886       i++;
4887     }
4888
4889   x = (bst->xgwa.width  - pix_w) / 2;
4890   y = (bst->xgwa.height - pix_h) / 2;
4891   if (y < 0) y = 0;
4892
4893   if (i > 0)
4894     {
4895       int j;
4896       XSetForeground (dpy, bst->gc,
4897                       get_pixel_resource (dpy, bst->xgwa.colormap,
4898                                           "atm.background",
4899                                           "ATM.Background"));
4900       for (j = -1; j < pix_w; j += i+1)
4901         XDrawLine (bst->dpy, pixmap, bst->gc, j, 0, j, pix_h);
4902       for (j = -1; j < pix_h; j += i+1)
4903         XDrawLine (bst->dpy, pixmap, bst->gc, 0, j, pix_w, j);
4904     }
4905
4906   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
4907
4908   XFreePixmap (dpy, pixmap);
4909
4910   return bst;
4911 }
4912
4913
4914 /* An Android phone boot loader, by jwz.
4915  */
4916 static struct bsod_state *
4917 android (Display *dpy, Window window)
4918 {
4919   struct bsod_state *bst = make_bsod_state (dpy, window, "android", "Android");
4920
4921   unsigned long bg = get_pixel_resource (dpy, bst->xgwa.colormap,
4922                                          "android.background",
4923                                          "Android.Background");
4924   unsigned long fg = get_pixel_resource (dpy, bst->xgwa.colormap,
4925                                          "android.foreground",
4926                                          "Android.Foreground");
4927   unsigned long c1 = get_pixel_resource (dpy, bst->xgwa.colormap,
4928                                          "android.color1",
4929                                          "Android.Foreground");
4930   unsigned long c2 = get_pixel_resource (dpy, bst->xgwa.colormap,
4931                                          "android.color2",
4932                                          "Android.Foreground");
4933   unsigned long c3 = get_pixel_resource (dpy, bst->xgwa.colormap,
4934                                          "android.color3",
4935                                          "Android.Foreground");
4936   unsigned long c4 = get_pixel_resource (dpy, bst->xgwa.colormap,
4937                                          "android.color4",
4938                                          "Android.Foreground");
4939   unsigned long c5 = get_pixel_resource (dpy, bst->xgwa.colormap,
4940                                          "android.color5",
4941                                          "Android.Foreground");
4942   unsigned long c6 = get_pixel_resource (dpy, bst->xgwa.colormap,
4943                                          "android.color6",
4944                                          "Android.Foreground");
4945   unsigned long c7 = get_pixel_resource (dpy, bst->xgwa.colormap,
4946                                          "android.color7",
4947                                          "Android.Foreground");
4948
4949   const char *lines0[] = {
4950     "Calculating... please wait\n",
4951     "osbl:     0x499DF907\n",
4952     "amss:     0x73162409\n",
4953     "hboot:    0xE46C3327\n",
4954     "boot:     0xBA570E7A\n",
4955     "recovery: 0xC8BBA213\n",
4956     "system:   0x87C3B1F0\n",
4957     "\n",
4958     "Press power key to go back.\n",
4959   };
4960
4961   const char *lines1[] = {
4962     "Checking SD card update...\n",
4963     "",
4964     "  SD Checking...\n",
4965     "  Failed to open zipfile\n",
4966     "  loading preload_content...\n",
4967     "  [Caution] Preload Content Not Found\n",
4968     "  loading HTCUpdateZipName image...\n",
4969     "",
4970     "  Checking...[PG46IMG.zip]\n",
4971     "Please plug off USB\n",
4972   };
4973
4974   const char *lines2[] = {
4975     "  SD Checking...\n",
4976     "  Loading...[PK76DIAG.zip]\n",
4977     "  No image!\n",
4978     "  Loading...[PK76DIAG.nbh]\n",
4979     "  No image or wrong image!\n",
4980     "  Loading...[PK76IMG.zip]\n",
4981     "  No image!\n",
4982     "  Loading...[PK76IMG.nbh]\n",
4983     "  No image or wrong image!\n",
4984     "  Loading...[PK76IMG.tar]\n",
4985     "  No image!\n",
4986     "  Loading...[PK76IMG.aes]\n",
4987     "  No image!\n",
4988     "  Loading...[PK76IMG.enc]\n",
4989     "  No image!\n",
4990   };
4991
4992   int cw = (bst->font->per_char
4993             ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
4994             : bst->font->min_bounds.width);
4995   int line_height = bst->font->ascent + bst->font->descent;
4996
4997   int state = 0;
4998
4999   Pixmap pixmap = 0;
5000   int pix_w = 0, pix_h = 0;
5001
5002 # ifdef DO_XPM
5003   pixmap = xpm_data_to_pixmap (dpy, window, (char **) android_skate,
5004                                &pix_w, &pix_h, 0);
5005   if (! pixmap) abort();
5006   bst->pixmap = pixmap;
5007 # endif /* DO_XPM */
5008
5009   bst->left_margin = (bst->xgwa.width - (cw * 40)) / 2;
5010   if (bst->left_margin < 0) bst->left_margin = 0;
5011
5012   while (1) {
5013     unsigned long delay =
5014       ((state == 0 ||
5015         state == countof(lines0) ||
5016         state == countof(lines0) + countof(lines1) ||
5017         state == countof(lines0) + countof(lines1) + countof(lines2))
5018                            ? 10000 : 0);
5019     BSOD_LINE_DELAY (bst, delay);
5020
5021     if (state <= countof(lines0) + countof(lines1) + countof(lines2))
5022       {
5023         BSOD_COLOR (bst, bg, bg);
5024         BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
5025         BSOD_COLOR (bst, bg, c1);
5026         BSOD_MOVETO (bst, bst->left_margin + bst->xoff,
5027                      bst->top_margin + bst->yoff + line_height);
5028         BSOD_TEXT (bst, LEFT, "*** UNLOCKED ***\n");
5029         BSOD_COLOR (bst, c2, bg);
5030         BSOD_TEXT (bst, LEFT,
5031                    "PRIMOU PVT SHIP S-OFF RL\n"
5032                    "HBOOT-1.17.0000\n"
5033                    "CPLD-None\n"
5034                    "MICROP-None\n"
5035                    "RADIO-3831.17.00.23_2\n"
5036                    "eMMC-bootmode: disabled\n"
5037                    "CPU-bootmode : disabled\n"
5038                    "HW Secure boot: enabled\n"
5039                    "MODEM PATH : OFF\n"
5040                    "May 15 2012, 10:28:15\n"
5041                    "\n");
5042         BSOD_COLOR (bst, bg, c3);
5043
5044         if (pixmap)
5045           {
5046             int x = (bst->xgwa.width - pix_w) / 2;
5047             int y = bst->xgwa.height - bst->yoff - pix_h;
5048             BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, x, y);
5049           }
5050       }
5051
5052     if (state == countof(lines0) ||
5053         state == countof(lines0) + countof(lines1) ||
5054         state == countof(lines0) + countof(lines1) + countof(lines2))
5055       {
5056         BSOD_TEXT (bst, LEFT, "HBOOT USB\n");
5057         BSOD_COLOR (bst, c4, bg);
5058         BSOD_TEXT (bst, LEFT,
5059                    "\n"
5060                    "<VOL UP> to previous item\n"
5061                    "<VOL DOWN> to next item\n"
5062                    "<POWER> to select item\n"
5063                    "\n");
5064         BSOD_COLOR (bst, c5, bg); BSOD_TEXT (bst, LEFT, "FASTBOOT\n");
5065         BSOD_COLOR (bst, c6, bg); BSOD_TEXT (bst, LEFT, "RECOVERY\n");
5066         BSOD_COLOR (bst, c7, bg); BSOD_TEXT (bst, LEFT, "FACTORY RESET\n");
5067         BSOD_COLOR (bst, c3, bg); BSOD_TEXT (bst, LEFT, "SIMLOCK\n");
5068         BSOD_COLOR (bst, bg, c3); BSOD_TEXT (bst, LEFT, "HBOOT USB\n");
5069         BSOD_COLOR (bst, fg, bg); BSOD_TEXT (bst, LEFT, "IMAGE CRC\n");
5070         BSOD_COLOR (bst, c3, bg); BSOD_TEXT (bst, LEFT, "SHOW BARCODE\n");
5071         BSOD_PAUSE (bst, 3000000);
5072       }
5073     else if (state < countof(lines0))
5074       {
5075         BSOD_TEXT (bst, LEFT, "IMAGE CRC\n\n");
5076         BSOD_COLOR (bst, c5, bg);
5077         {
5078           int i;
5079           for (i = 0; i <= state; i++) {
5080             const char *s = lines0[i];
5081             BSOD_COLOR (bst, (strchr(s, ':') ? c7 : c3), bg);
5082             BSOD_TEXT (bst, LEFT, s);
5083           }
5084         }
5085         BSOD_PAUSE (bst, 500000);
5086         if (state == countof(lines0)-1)
5087           BSOD_PAUSE (bst, 2000000);
5088       }
5089     else if (state < countof(lines0) + countof(lines1))
5090       {
5091         BSOD_TEXT (bst, LEFT, "HBOOT\n\n");
5092         BSOD_COLOR (bst, c5, bg);
5093         {
5094           int i;
5095           for (i = countof(lines0); i <= state; i++) {
5096             const char *s = lines1[i - countof(lines0)];
5097             BSOD_COLOR (bst, (*s == ' ' ? c6 : c3), bg);
5098             BSOD_TEXT (bst, LEFT, s);
5099           }
5100         }
5101         BSOD_PAUSE (bst, 500000);
5102         if (state == countof(lines0) + countof(lines1) - 1)
5103           BSOD_PAUSE (bst, 2000000);
5104       }
5105     else if (state < countof(lines0) + countof(lines1) + countof(lines2))
5106       {
5107         BSOD_TEXT (bst, LEFT, "HBOOT USB\n\n");
5108         BSOD_COLOR (bst, c5, bg);
5109         {
5110           int i;
5111           for (i = countof(lines0) + countof(lines1); i <= state; i++) {
5112             const char *s = lines2[i - countof(lines0) - countof(lines1)];
5113             BSOD_COLOR (bst, (*s == ' ' ? c6 : c3), bg);
5114             BSOD_TEXT (bst, LEFT, s);
5115           }
5116         }
5117         BSOD_PAUSE (bst, 500000);
5118         if (state == countof(lines0) + countof(lines1) + countof(lines2)-1)
5119           BSOD_PAUSE (bst, 2000000);
5120       }
5121     else
5122       break;
5123
5124     state++;
5125   }
5126
5127   XClearWindow (dpy, window);
5128
5129   return bst;
5130 }
5131
5132
5133
5134
5135 /*****************************************************************************
5136  *****************************************************************************/
5137
5138
5139 static const struct {
5140   const char *name;
5141   struct bsod_state * (*fn) (Display *, Window);
5142 } all_modes[] = {
5143   { "Windows",          windows_31 },
5144   { "NT",               windows_nt },
5145   { "Win2K",            windows_other },
5146   { "Win10",            windows_10 },
5147   { "Ransomware",       windows_ransomware },
5148   { "Amiga",            amiga },
5149   { "Mac",              mac },
5150   { "MacsBug",          macsbug },
5151   { "Mac1",             mac1 },
5152   { "MacX",             macx },
5153   { "SCO",              sco },
5154   { "HVX",              hvx },
5155   { "HPPALinux",        hppa_linux },
5156   { "SparcLinux",       sparc_linux },
5157   { "BSD",              bsd },
5158   { "Atari",            atari },
5159 #ifndef HAVE_JWXYZ
5160   { "BlitDamage",       blitdamage },
5161 #endif
5162   { "Solaris",          sparc_solaris },
5163   { "Linux",            linux_fsck },
5164   { "HPUX",             hpux },
5165   { "OS390",            os390 },
5166   { "Tru64",            tru64 },
5167   { "VMS",              vms },
5168   { "OS2",              os2 },
5169   { "MSDOS",            msdos },
5170   { "Nvidia",           nvidia },
5171   { "Apple2",           apple2crash },
5172   { "ATM",              atm },
5173   { "GLaDOS",           glados },
5174   { "Android",          android },
5175   { "VMware",           vmware },
5176 };
5177
5178
5179 struct driver_state {
5180   const char *name;
5181   int only, which, next_one;
5182   int mode_duration;
5183   int delay_remaining;
5184   time_t start;
5185   Bool debug_p, cycle_p;
5186   struct bsod_state *bst;
5187 };
5188
5189
5190 static void
5191 hack_title (struct driver_state *dst)
5192 {
5193 # ifndef HAVE_JWXYZ
5194   char *oname = 0;
5195   XFetchName (dst->bst->dpy, dst->bst->window, &oname);
5196   if (oname && !strncmp (oname, "BSOD: ", 6)) {
5197     char *tail = oname + 4;
5198     char *s = strchr (tail+1, ':');
5199     char *nname;
5200     if (s) tail = s;
5201     nname = malloc (strlen (tail) + strlen (dst->name) + 20);
5202     sprintf (nname, "BSOD: %s%s", dst->name, tail);
5203     XStoreName (dst->bst->dpy, dst->bst->window, nname);
5204     free (nname);
5205   }
5206 # endif /* !HAVE_JWXYZ */
5207 }
5208
5209 static void *
5210 bsod_init (Display *dpy, Window window)
5211 {
5212   struct driver_state *dst = (struct driver_state *) calloc (1, sizeof(*dst));
5213   char *s;
5214
5215   dst->mode_duration = get_integer_resource (dpy, "delay", "Integer");
5216   if (dst->mode_duration < 3) dst->mode_duration = 3;
5217
5218   dst->debug_p = get_boolean_resource (dpy, "debug", "Boolean");
5219
5220   dst->only = -1;
5221   dst->next_one = -1;
5222   s = get_string_resource(dpy, "doOnly", "DoOnly");
5223   if (s && !strcasecmp (s, "cycle"))
5224     {
5225       dst->which = -1;
5226       dst->cycle_p = True;
5227     }
5228   else if (s && *s)
5229     {
5230       int count = countof(all_modes);
5231       for (dst->only = 0; dst->only < count; dst->only++)
5232         if (!strcasecmp (s, all_modes[dst->only].name))
5233           break;
5234       if (dst->only >= count)
5235         {
5236           fprintf (stderr, "%s: unknown -only mode: \"%s\"\n", progname, s);
5237           dst->only = -1;
5238         }
5239     }
5240   if (s) free (s);
5241
5242   dst->name = "none";
5243   dst->which = -1;
5244   return dst;
5245 }
5246
5247
5248 static unsigned long
5249 bsod_draw (Display *dpy, Window window, void *closure)
5250 {
5251   struct driver_state *dst = (struct driver_state *) closure;
5252   time_t now;
5253   int time_left;
5254
5255  AGAIN:
5256   now = time ((time_t *) 0);
5257   time_left = dst->start + dst->mode_duration - now;
5258
5259   if (dst->bst && dst->bst->img_loader)   /* still loading */
5260     {
5261       dst->bst->img_loader =
5262         load_image_async_simple (dst->bst->img_loader, 0, 0, 0, 0, 0);
5263       return 100000;
5264     }
5265
5266  DELAY_NOW:
5267   /* Rather than returning a multi-second delay from the draw() routine,
5268      meaning "don't call us again for N seconds", we quantize that down
5269      to 1/10th second intervals so that it's more responsive to
5270      rotate/reshape events.
5271    */
5272   if (dst->delay_remaining)
5273     {
5274       int inc = 10000;
5275       int this_delay = MIN (dst->delay_remaining, inc);
5276       dst->delay_remaining = MAX (0, dst->delay_remaining - inc);
5277       return this_delay;
5278     }
5279
5280   if (! dst->bst && time_left > 0)      /* run completed; wait out the delay */
5281     {
5282       if (dst->debug_p)
5283         fprintf (stderr, "%s: %s: %d left\n", progname, dst->name, time_left);
5284       dst->start = 0;
5285       if (time_left > 5) time_left = 5;  /* Boooored now */
5286       dst->delay_remaining = 1000000 * time_left;
5287     }
5288
5289   else if (dst->bst)                    /* sub-mode currently running */
5290     {
5291       int this_delay = -1;
5292
5293       if (time_left > 0)
5294         this_delay = bsod_pop (dst->bst);
5295
5296       /* XSync (dpy, False);  slows down char drawing too much on HAVE_JWXYZ */
5297
5298       if (this_delay == 0)
5299         goto AGAIN;                     /* no delay, not expired: stay here */
5300       else if (this_delay >= 0)
5301         {
5302           dst->delay_remaining = this_delay;    /* return; time to sleep */
5303           goto DELAY_NOW;
5304         }
5305       else
5306         {                               /* sub-mode run completed or expired */
5307           if (dst->debug_p)
5308             fprintf (stderr, "%s: %s: done\n", progname, dst->name);
5309           free_bsod_state (dst->bst);
5310           dst->bst = 0;
5311           return 0;
5312         }
5313     }
5314   else                                  /* launch a new sub-mode */
5315     {
5316       if (dst->next_one >= 0)
5317         dst->which = dst->next_one, dst->next_one = -1;
5318       else if (dst->cycle_p)
5319         dst->which = (dst->which + 1) % countof(all_modes);
5320       else if (dst->only >= 0)
5321         dst->which = dst->only;
5322       else
5323         {
5324           int count = countof(all_modes);
5325           int i;
5326
5327           for (i = 0; i < 200; i++)
5328             {
5329               char name[100], class[100];
5330               int new_mode = (random() & 0xFF) % count;
5331
5332               if (i < 100 && new_mode == dst->which)
5333                 continue;
5334
5335               sprintf (name,  "do%s", all_modes[new_mode].name);
5336               sprintf (class, "Do%s", all_modes[new_mode].name);
5337
5338               if (get_boolean_resource (dpy, name, class))
5339                 {
5340                   dst->which = new_mode;
5341                   break;
5342                 }
5343             }
5344
5345           if (i >= 200)
5346             {
5347               fprintf (stderr, "%s: no display modes enabled?\n", progname);
5348               /* exit (-1); */
5349               dst->which = dst->only = 0;
5350             }
5351         }
5352
5353       if (dst->debug_p)
5354         fprintf (stderr, "%s: %s: launch\n", progname,
5355                  all_modes[dst->which].name);
5356
5357       /* Run the mode setup routine...
5358        */
5359       if (dst->bst) abort();
5360       dst->name  = all_modes[dst->which].name;
5361       dst->bst   = all_modes[dst->which].fn (dpy, window);
5362       dst->start = (dst->bst ? time ((time_t *) 0) : 0);
5363
5364       /* Reset the structure run state to the beginning,
5365          and do some sanitization of the cursor position
5366          before the first run.
5367        */
5368       if (dst->bst)
5369         {
5370           if (dst->debug_p)
5371             fprintf (stderr, "%s: %s: queue size: %d (%d)\n", progname,
5372                      dst->name, dst->bst->pos, dst->bst->queue_size);
5373
5374           hack_title (dst);
5375           dst->bst->pos = 0;
5376           dst->bst->x = dst->bst->current_left =
5377             dst->bst->left_margin + dst->bst->xoff;
5378
5379           if (dst->bst->y < 
5380               dst->bst->top_margin + dst->bst->yoff + dst->bst->font->ascent)
5381             dst->bst->y =
5382               dst->bst->top_margin + dst->bst->yoff + dst->bst->font->ascent;
5383         }
5384     }
5385
5386   return 0;
5387 }
5388
5389
5390 static void
5391 bsod_reshape (Display *dpy, Window window, void *closure,
5392               unsigned int w, unsigned int h)
5393 {
5394   struct driver_state *dst = (struct driver_state *) closure;
5395
5396   if (dst->bst &&
5397       w == dst->bst->xgwa.width &&
5398       h == dst->bst->xgwa.height)
5399     return;
5400
5401   if (dst->debug_p)
5402     fprintf (stderr, "%s: %s: reshape reset\n", progname, dst->name);
5403
5404   /* just restart this mode and restart when the window is resized. */
5405   if (dst->bst)
5406     free_bsod_state (dst->bst);
5407   dst->bst = 0;
5408   dst->start = 0;
5409   dst->delay_remaining = 0;
5410   dst->next_one = dst->which;
5411   dst->name = "none";
5412   XClearWindow (dpy, window);
5413 }
5414
5415
5416 static Bool
5417 bsod_event (Display *dpy, Window window, void *closure, XEvent *event)
5418 {
5419   struct driver_state *dst = (struct driver_state *) closure;
5420   Bool reset_p = False;
5421
5422   /* pick a new mode and restart when mouse clicked, or certain keys typed. */
5423
5424   if (screenhack_event_helper (dpy, window, event))
5425     reset_p = True;
5426
5427   if (reset_p)
5428     {
5429       if (dst->debug_p)
5430         fprintf (stderr, "%s: %s: manual reset\n", progname, dst->name);
5431       if (dst->bst)
5432         free_bsod_state (dst->bst);
5433       dst->bst = 0;
5434       dst->start = 0;
5435       dst->delay_remaining = 0;
5436       dst->name = "none";
5437       XClearWindow (dpy, window);
5438       return True;
5439     }
5440   else
5441     return False;
5442 }
5443
5444
5445 static void
5446 bsod_free (Display *dpy, Window window, void *closure)
5447 {
5448   struct driver_state *dst = (struct driver_state *) closure;
5449   if (dst->bst)
5450     free_bsod_state (dst->bst);
5451   free (dst);
5452 }
5453
5454
5455 static const char *bsod_defaults [] = {
5456   "*delay:                 45",
5457   "*debug:                 False",
5458
5459   "*doOnly:                ",
5460   "*doWindows:             True",
5461   "*doNT:                  True",
5462   "*doWin2K:               True",
5463   "*doWin10:               True",
5464   "*doRansomware:          True",
5465   "*doAmiga:               True",
5466   "*doMac:                 True",
5467   "*doMacsBug:             True",
5468   "*doMac1:                True",
5469   "*doMacX:                True",
5470   "*doSCO:                 True",
5471   "*doAtari:               False",      /* boring */
5472   "*doBSD:                 False",      /* boring */
5473   "*doLinux:               True",
5474   "*doSparcLinux:          False",      /* boring */
5475   "*doHPPALinux:           True",
5476   "*doBlitDamage:          True",
5477   "*doSolaris:             True",
5478   "*doHPUX:                True",
5479   "*doTru64:               True",
5480   "*doApple2:              True",
5481   "*doOS390:               True",
5482   "*doVMS:                 True",
5483   "*doHVX:                 True",
5484   "*doMSDOS:               True",
5485   "*doOS2:                 True",
5486   "*doNvidia:              True",
5487   "*doATM:                 True",
5488   "*doGLaDOS:              True",
5489   "*doAndroid:             True",
5490   "*doVMware:              True",
5491
5492   ".foreground:            White",
5493   ".background:            Black",
5494
5495   ".windows.foreground:    White",
5496   ".windows.background:    #0000AA",    /* EGA color 0x01. */
5497
5498   ".nt.foreground:         White",
5499   ".nt.background:         #0000AA",    /* EGA color 0x01. */
5500
5501   ".windowslh.foreground:  White",
5502   ".windowslh.background:  #AA0000",    /* EGA color 0x04. */
5503   ".windowslh.background2: #AAAAAA",    /* EGA color 0x07. */
5504
5505   ".win10.foreground:      White",
5506   ".win10.background:      #1070AA",
5507
5508   ".ransomware.foreground:   White",
5509   ".ransomware.background:   #841212",
5510   ".ransomware.foreground2:  Black",      /* ransom note */
5511   ".ransomware.background2:  White",
5512   ".ransomware.foreground3:  Black",      /* buttons */
5513   ".ransomware.background3:  #AAAAAA",
5514   ".ransomware.link:         #7BF9F6",
5515   ".ransomware.timerheader:  #BDBE02",
5516
5517
5518   ".glaDOS.foreground:     White",
5519   ".glaDOS.background:     #0000AA",    /* EGA color 0x01. */
5520
5521   ".amiga.foreground:      #FF0000",
5522   ".amiga.background:      Black",
5523   ".amiga.background2:     White",
5524
5525   ".mac.foreground:        #BBFFFF",
5526   ".mac.background:        Black",
5527
5528   ".atari.foreground:      Black",
5529   ".atari.background:      White",
5530
5531   ".macsbug.foreground:    Black",
5532   ".macsbug.background:    White",
5533   ".macsbug.borderColor:   #AAAAAA",
5534
5535   ".mac1.foreground:       Black",
5536   ".mac1.background:       White",
5537
5538   ".macx.foreground:       White",
5539   ".macx.textForeground:   White",
5540   ".macx.textBackground:   Black",
5541   ".macx.background:       #888888",
5542
5543   ".macinstall.barForeground: #C0C0C0",
5544   ".macinstall.barBackground: #888888",
5545
5546   ".sco.foreground:        White",
5547   ".sco.background:        Black",
5548
5549   ".hvx.foreground:        White",
5550   ".hvx.background:        Black",
5551
5552   ".linux.foreground:      White",
5553   ".linux.background:      Black",
5554
5555   ".hppalinux.foreground:  White",
5556   ".hppalinux.background:  Black",
5557
5558   ".sparclinux.foreground: White",
5559   ".sparclinux.background: Black",
5560
5561   ".bsd.foreground:        #c0c0c0",
5562   ".bsd.background:        Black",
5563
5564   ".solaris.foreground:    Black",
5565   ".solaris.background:    White",
5566
5567   ".hpux.foreground:       White",
5568   ".hpux.background:       Black",
5569
5570   ".os390.background:      Black",
5571   ".os390.foreground:      Red",
5572
5573   ".tru64.foreground:      White",
5574   ".tru64.background:      #0000AA",    /* EGA color 0x01. */
5575
5576   ".vms.foreground:        White",
5577   ".vms.background:        Black",
5578
5579   ".msdos.foreground:      White",
5580   ".msdos.background:      Black",
5581
5582   ".os2.foreground:        White",
5583   ".os2.background:        Black",
5584
5585   ".atm.foreground:        Black",
5586   ".atm.background:        #FF6600",
5587
5588   ".android.foreground:    Black",
5589   ".android.background:    White",
5590   ".android.color1:        #AA00AA", /* violet */
5591   ".android.color2:        #336633", /* green1 */
5592   ".android.color3:        #0000FF", /* blue */
5593   ".android.color4:        #CC7744", /* orange */
5594   ".android.color5:        #99AA55", /* green2 */
5595   ".android.color6:        #66AA33", /* green3 */
5596   ".android.color7:        #FF0000", /* red */
5597
5598   ".vmware.foreground:     White",
5599   ".vmware.foreground2:    Yellow",
5600   ".vmware.background:     #a700a8",    /* purple */
5601
5602   "*dontClearRoot:         True",
5603
5604   ANALOGTV_DEFAULTS
5605
5606 #ifdef HAVE_XSHM_EXTENSION
5607   "*useSHM:                True",
5608 #endif
5609
5610   "*fontB:                 ",
5611   "*fontC:                 ",
5612
5613 # if defined(USE_IPHONE)
5614
5615   "*font:                  PxPlus IBM VGA8 16, Courier-Bold 14",
5616   "*bigFont:               ",
5617   "*font2:                 ",
5618   "*bigFont2:              ",
5619
5620   ".mac.font:              Courier-Bold 18",
5621   ".macsbug.font:          Courier-Bold 8",
5622   ".macx.font:             Courier-Bold 14",
5623   ".macdisk.font:          Courier-Bold 14",
5624   ".macinstall.font:       Helvetica 12, Arial 12",
5625   ".macinstall.bigFont:    Helvetica 12, Arial 12",
5626   ".msdos.font:            PxPlus IBM VGA8 32, Courier-Bold 28",
5627   ".nt.font:               PxPlus IBM VGA8 12, Courier-Bold 10",
5628   ".win10.font:            Arial 12, Helvetica 12",
5629   ".win10.bigFont:         Arial 12, Helvetica 12",
5630   ".win10.fontB:           Arial 50, Helvetica 50",
5631   ".win10.fontC:           Arial 9, Helvetica 9",
5632   ".win10.bigFont2:        ",
5633
5634   ".ransomware.font:         Arial 10, Helvetica 10",
5635   ".ransomware.fontB:        Arial 8, Helvetica 8",
5636   ".ransomware.fontC:        Arial 10, Helvetica Bold 10",
5637
5638 # elif defined(HAVE_ANDROID)
5639
5640   "*font:                  PxPlus IBM VGA8 16",
5641   "*bigFont:               ",
5642   "*font2:                 ",
5643   "*bigFont2:              ",
5644
5645   ".mac.font:              -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
5646   ".macsbug.font:          -*-courier-bold-r-*-*-*-80-*-*-m-*-*-*",
5647   ".macx.font:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5648   ".macdisk.font:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5649   ".macinstall.font:       -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
5650   ".macinstall.bigFont:    -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
5651   ".msdos.font:            PxPlus IBM VGA8 32",
5652   ".nt.font:               PxPlus IBM VGA8 12",
5653
5654   ".win10.font:            -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
5655   ".win10.bigFont:         -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
5656   ".win10.fontB:           -*-helvetica-medium-r-*-*-*-500-*-*-*-*-*-*",
5657   ".win10.fontC:           -*-helvetica-medium-r-*-*-*-90-*-*-*-*-*-*",
5658   ".win10.bigFont2:        ",
5659
5660   ".ransomware.font:       -*-helvetica-medium-r-*-*-*-100-*-*-*-*-*-*",
5661   ".ransomware.fontB:      -*-helvetica-medium-r-*-*-*-80-*-*-*-*-*-*",
5662   ".ransomware.fontC:      -*-helvetica-bold-r-*-*-*-100-*-*-*-*-*-*",
5663
5664 # elif defined(HAVE_COCOA)
5665
5666   "*font:                  PxPlus IBM VGA8 8,  Courier Bold 9",
5667   "*bigFont:               PxPlus IBM VGA8 32, Courier Bold 24",
5668   "*font2:                 ",
5669   "*bigFont2:              ",
5670
5671   ".mac.font:              Monaco 10, Courier Bold 9",
5672   ".mac.bigFont:           Monaco 18, Courier Bold 18",
5673
5674   ".macsbug.font:          Monaco 10, Courier Bold 9",
5675   ".macsbug.bigFont:       Monaco 24, Courier Bold 24",
5676
5677   ".macx.font:             Courier Bold 9",
5678   ".macx.bigFont:          Courier Bold 14",
5679   ".macdisk.font:          Courier Bold 9",
5680   ".macdisk.bigFont:       Courier Bold 18",
5681   ".macinstall.font:       Helvetica 24, Arial 24",
5682   ".macinstall.bigFont:    Helvetica 24, Arial 24",
5683
5684   ".hvx.bigFont:           PxPlus IBM VGA8 16, Courier Bold 14",
5685   ".hppalinux.bigFont:     PxPlus IBM VGA8 16, Courier Bold 14",
5686   ".solaris.bigFont:       PxPlus IBM VGA8 16, Courier Bold 14",
5687   ".linux.bigFont:         PxPlus IBM VGA8 16, Courier Bold 14",
5688   ".hpux.bigFont:          PxPlus IBM VGA8 16, Courier Bold 14",
5689   ".msdos.font:            PxPlus IBM VGA8 16, Courier Bold 14",
5690
5691   ".win10.font:            Arial 24, Helvetica 24",
5692   ".win10.bigFont:         Arial 24, Helvetica 24",
5693   ".win10.fontB:           Arial 100, Helvetica 100",
5694   ".win10.fontC:           Arial 16, Helvetica 16",
5695   ".win10.bigFont2:        ",
5696
5697   ".ransomware.font:         Arial 24, Helvetica 24",
5698   ".ransomware.bigFont:      Arial 24, Helvetica 24",
5699   ".ransomware.fontB:        Arial 16, Helvetica 16",
5700   ".ransomware.fontC:        Arial Bold 24, Helvetica Bold 24",
5701
5702 # else   /* X11 */
5703
5704   "*font:                  9x15bold",
5705   "*font2:                 -*-courier-bold-r-*-*-*-120-*-*-m-*-*-*",
5706   "*bigFont:               -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
5707   "*bigFont2:              -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
5708
5709   ".macsbug.font:          -*-courier-medium-r-*-*-*-80-*-*-m-*-*-*",
5710   ".macsbug.bigFont:       -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5711
5712   ".macdisk.font:          -*-courier-bold-r-*-*-*-80-*-*-m-*-*-*",
5713   ".macdisk.bigFont:       -*-courier-bold-r-*-*-*-100-*-*-m-*-*-*",
5714   ".macinstall.font:       -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5715   ".macinstall.bigFont:    -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5716
5717   ".sco.font:              -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5718   ".hvx.font:              -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5719   ".hppalinux.bigFont:     -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5720   ".sparclinux.bigFont:    -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5721
5722   ".bsd.font:              vga",
5723   ".bsd.bigFont:           -sun-console-medium-r-*-*-22-*-*-*-m-*-*-*",
5724   ".bsd.bigFont2:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5725
5726   ".solaris.font:          -sun-gallant-*-*-*-*-19-*-*-*-*-120-*-*",
5727   ".hpux.bigFont:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5728   ".os390.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5729   ".tru64.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5730   ".vms.bigFont:           -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5731   ".msdos.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5732
5733   ".win10.font:            -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5734   ".win10.bigFont:         -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5735   ".win10.fontB:           -*-helvetica-medium-r-*-*-*-240-*-*-*-*-*-*",
5736   ".win10.fontC:           -*-helvetica-medium-r-*-*-*-140-*-*-*-*-*-*",
5737   ".win10.font2:           ",
5738   ".win10.bigFont2:        ",
5739
5740   ".ransomware.font:       -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5741   ".ransomware.bigFont:    -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5742   ".ransomware.fontB:      -*-helvetica-medium-r-*-*-*-140-*-*-*-*-*-*",
5743   ".ransomware.fontC:      -*-helvetica-bold-r-*-*-*-180-*-*-*-*-*-*",
5744
5745
5746 # endif  /* X11 */
5747
5748   0
5749 };
5750
5751 static const XrmOptionDescRec bsod_options [] = {
5752   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
5753   { "-only",            ".doOnly",              XrmoptionSepArg, 0 },
5754   { "-debug",           ".debug",               XrmoptionNoArg,  "True"  },
5755   { "-windows",         ".doWindows",           XrmoptionNoArg,  "True"  },
5756   { "-no-windows",      ".doWindows",           XrmoptionNoArg,  "False" },
5757   { "-nt",              ".doNT",                XrmoptionNoArg,  "True"  },
5758   { "-no-nt",           ".doNT",                XrmoptionNoArg,  "False" },
5759   { "-2k",              ".doWin2K",             XrmoptionNoArg,  "True"  },
5760   { "-no-2k",           ".doWin2K",             XrmoptionNoArg,  "False" },
5761   { "-win10",           ".doWin10",             XrmoptionNoArg,  "True"  },
5762   { "-no-win10",        ".doWin10",             XrmoptionNoArg,  "False" },
5763   { "-ransomware",      ".doRansomware",        XrmoptionNoArg,  "True"  },
5764   { "-no-ransomware",   ".doRansomware",        XrmoptionNoArg,  "False" },
5765   { "-amiga",           ".doAmiga",             XrmoptionNoArg,  "True"  },
5766   { "-no-amiga",        ".doAmiga",             XrmoptionNoArg,  "False" },
5767   { "-mac",             ".doMac",               XrmoptionNoArg,  "True"  },
5768   { "-no-mac",          ".doMac",               XrmoptionNoArg,  "False" },
5769   { "-mac1",            ".doMac1",              XrmoptionNoArg,  "True"  },
5770   { "-no-mac1",         ".doMac1",              XrmoptionNoArg,  "False" },
5771   { "-macx",            ".doMacX",              XrmoptionNoArg,  "True"  },
5772   { "-no-macx",         ".doMacX",              XrmoptionNoArg,  "False" },
5773   { "-atari",           ".doAtari",             XrmoptionNoArg,  "True"  },
5774   { "-no-atari",        ".doAtari",             XrmoptionNoArg,  "False" },
5775   { "-macsbug",         ".doMacsBug",           XrmoptionNoArg,  "True"  },
5776   { "-no-macsbug",      ".doMacsBug",           XrmoptionNoArg,  "False" },
5777   { "-apple2",          ".doApple2",            XrmoptionNoArg,  "True"  },
5778   { "-no-apple2",       ".doApple2",            XrmoptionNoArg,  "False" },
5779   { "-sco",             ".doSCO",               XrmoptionNoArg,  "True"  },
5780   { "-no-sco",          ".doSCO",               XrmoptionNoArg,  "False" },
5781   { "-hvx",             ".doHVX",               XrmoptionNoArg,  "True"  },
5782   { "-no-hvx",          ".doHVX",               XrmoptionNoArg,  "False" },
5783   { "-bsd",             ".doBSD",               XrmoptionNoArg,  "True"  },
5784   { "-no-bsd",          ".doBSD",               XrmoptionNoArg,  "False" },
5785   { "-linux",           ".doLinux",             XrmoptionNoArg,  "True"  },
5786   { "-no-linux",        ".doLinux",             XrmoptionNoArg,  "False" },
5787   { "-hppalinux",       ".doHPPALinux",         XrmoptionNoArg,  "True"  },
5788   { "-no-hppalinux",    ".doHPPALinux",         XrmoptionNoArg,  "False" },
5789   { "-sparclinux",      ".doSparcLinux",        XrmoptionNoArg,  "True"  },
5790   { "-no-sparclinux",   ".doSparcLinux",        XrmoptionNoArg,  "False" },
5791   { "-blitdamage",      ".doBlitDamage",        XrmoptionNoArg,  "True"  },
5792   { "-no-blitdamage",   ".doBlitDamage",        XrmoptionNoArg,  "False" },
5793   { "-nvidia",          ".doNvidia",            XrmoptionNoArg,  "True"  },
5794   { "-no-nvidia",       ".doNvidia",            XrmoptionNoArg,  "False" },
5795   { "-solaris",         ".doSolaris",           XrmoptionNoArg,  "True"  },
5796   { "-no-solaris",      ".doSolaris",           XrmoptionNoArg,  "False" },
5797   { "-hpux",            ".doHPUX",              XrmoptionNoArg,  "True"  },
5798   { "-no-hpux",         ".doHPUX",              XrmoptionNoArg,  "False" },
5799   { "-os390",           ".doOS390",             XrmoptionNoArg,  "True"  },
5800   { "-no-os390",        ".doOS390",             XrmoptionNoArg,  "False" },
5801   { "-tru64",           ".doHPUX",              XrmoptionNoArg,  "True"  },
5802   { "-no-tru64",        ".doTru64",             XrmoptionNoArg,  "False" },
5803   { "-vms",             ".doVMS",               XrmoptionNoArg,  "True"  },
5804   { "-no-vms",          ".doVMS",               XrmoptionNoArg,  "False" },
5805   { "-msdos",           ".doMSDOS",             XrmoptionNoArg,  "True"  },
5806   { "-no-msdos",        ".doMSDOS",             XrmoptionNoArg,  "False" },
5807   { "-os2",             ".doOS2",               XrmoptionNoArg,  "True"  },
5808   { "-no-os2",          ".doOS2",               XrmoptionNoArg,  "False" },
5809   { "-atm",             ".doATM",               XrmoptionNoArg,  "True"  },
5810   { "-no-atm",          ".doATM",               XrmoptionNoArg,  "False" },
5811   { "-glados",          ".doGLaDOS",            XrmoptionNoArg,  "True"  },
5812   { "-no-glados",       ".doGLaDOS",            XrmoptionNoArg,  "False" },
5813   { "-android",         ".doAndroid",           XrmoptionNoArg,  "True"  },
5814   { "-no-android",      ".doAndroid",           XrmoptionNoArg,  "False" },
5815   { "-vmware",          ".doVMware",            XrmoptionNoArg,  "True"  },
5816   { "-no-vmware",       ".doVMware",            XrmoptionNoArg,  "False" },
5817   ANALOGTV_OPTIONS
5818   { 0, 0, 0, 0 }
5819 };
5820
5821
5822 XSCREENSAVER_MODULE ("BSOD", bsod)