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