From http://www.jwz.org/xscreensaver/xscreensaver-5.40.tar.gz
[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     "Creepto-Currency",
1537     "secret sauce",
1538     "Tribbles",
1539   };
1540
1541   const char *currency = currencies[random() % countof(currencies)];
1542
1543   const char *header_quips[] = {
1544     "Oops, your screens have been encrypted!",
1545     "Oops, your screens have been encrypted!",
1546     "Oops, your screens have been encrypted!",
1547     "Oops, your screens have been encrypted!",
1548     "Oops, your screen have encrypted!",
1549     "Oops, you're screens have been encrypted!",
1550     "Oops, your screens have been encrupted!",
1551     "Oops, your screens have been encrumpet!",
1552     "Oops, your screens have been encrusted!",
1553     "If you don't pay this ransom, then you are a theif!",
1554     "Your screen was subject to the laws of mathomatics!",
1555     "Oops, your screen was shaved by Occam's Razor!",
1556     "Oops, your screen was perturbated by Langford's Basilisk!",
1557     "Your screen is now stored as Snapchat messages!",
1558     "Oops, your screen is now stored on Betamax!",
1559     "Oops, your screen is now in the clown!",
1560     "Oops, your screen has been deprecated!",
1561     "Oops, you're screen was seized by the FBI!",
1562     "All your screen was shared with your coworkers!",
1563     "All your screen are belong to us.",
1564     "Well actually, your screen isn't needed anymore.",
1565     "u just got popped with some 0day shit!!",
1566     "M'lady,",
1567   };
1568
1569   const char *header_quip = header_quips[random() % countof(header_quips)];
1570
1571   /* You got this because... */
1572   const char *excuse_quips[] = {
1573     "all human actions are equivalent and all are on principle doomed "
1574     "to failure",
1575     "you hold a diverse portfolio of cryptocurrencies",
1576     "you need to get in on ransomware futures at the ground floor",
1577     "your flight was overbooked",
1578     "you did not apply the security update for bugs NSA keys secret from "
1579     "Microsoft in your Windows(R) operating system",
1580     "you are bad and you should feel bad",
1581     "you used the wifi at defcon",
1582     "you lack official Clown Strike[TM] threaty threat technology",
1583   };
1584
1585   const char *excuse_quip = excuse_quips[random() % countof(excuse_quips)];
1586
1587   /* WELL ACTUALLY, screensavers aren't really nescessary anymore because... */
1588   const char *screensaver_quips[] = {
1589     "I read it on hacker news",
1590     "that's official Debian policy now",
1591     "that is the official policy of United Airlines",
1592     "they cause global warming",
1593     "they lack an eternal struggle",
1594     "they lack a vapid dichotomy",
1595     "those electrons could be used for gold farming instead",
1596     "you can make more money in art exhibitions",
1597   };
1598
1599   const char *screensaver_quip =
1600     screensaver_quips[random() % countof(screensaver_quips)];
1601
1602   const char *lines[] = {
1603     "*What Happened To My Computer?\n",
1604     "Your important pixels are paintcrypted. All of your documents, photos, ",
1605     "videos, databases, icons, dick pics are not accessible because they ",
1606     "have been bitblted. Maybe you are looking for a way to get them back, ",
1607     "but don't waste your time. Nobody can recover your pixels without our ",
1608     "pointer motion clicker services.\n",
1609     "\n",
1610     "*Can I Recover My Important Dick Pix?\n",
1611     "Yes. We guarantee that you can recover them safely and easily. But you ",
1612     "not have much time.\n",
1613     "You can expose some files for free. Try it now by pressing <The Any ",
1614     "Key>.\n",
1615     "But if you want to unsave all your screens, then you need to pay. ",
1616     "You have only 3 days to click. After that the clicks will double. ",
1617     "After 7 days your pixels will be gone forever.\n",
1618     "We will have free events for cheapskates who can't pay in 6 months, ",
1619     "long after all the pixels are xored.\n",
1620     "\n",
1621     "*How do I pay?\n",
1622     "Payment is accepted in ", "[C]",
1623     " only. For more information, press <About ", "[C]", ">.",
1624     " Please check the current price of ", "[C]", " and buy some ", "[C]",
1625     ". For more information, press <How to buy ", "[C]", ">.\n",
1626     "And send the correct amount to the address specified below. After your ",
1627     "payment, press <Check Payment>. Best time to check: 4-6am, Mon-Fri.\n",
1628     "\n",
1629     "*Why Did I Get This?\n",
1630     "You got this because ", "[Q]",
1631     ". Also you didn't click hard enough and now Tinkerbelle is dead.\n",
1632     "\n",
1633     "*But Aren't Screensavers Are Necessary?\n",
1634     "WELL ACTUALLY, screensavers aren't really nescessary anymore because ",
1635     "[S]", ".\n",
1636     "\n",
1637     "Please file complaints to @POTUS on Twitter.\n",
1638     "\n"
1639     "\n"
1640     "\n"
1641     "\n",
1642     "*GREETZ TO CRASH OVERRIDE AND ALSO JOEY\n",
1643   };
1644
1645   /* Positions of UI elements. Layout:
1646
1647    +---------+-+---------------------------------------+
1648    |   LOGO  | |               HEADER                  |
1649    |         | |---------------------------------------|
1650    |         | | NOTE TEXT                             |
1651    |   DEAD  | |                                       |
1652    |   LINE  | |                                       |
1653    |  TIMERS | |                                       |
1654    |         | |                                       |
1655    |         | |                                       |
1656    |         | |                                       |
1657    |         | |                                       |
1658    |         | |                                       |
1659    +---------+ |                                       |
1660    | LINKS   | +---------------------------------------+
1661    | LINKS   | | FOOTER                                |
1662    +---------+-+---------------------------------------+
1663
1664   The right side of the UI maximises to available width.
1665   The note text maximises to available height.
1666   The logo, header and timers are anchored to the top left of the window.
1667   The links and footer are anchored to the bottom left of the window.
1668   The entire window is a fixed 4:3 scale, with a minimum margin around it.
1669   */
1670
1671   /* main window text */
1672   unsigned long fg = bst->fg;
1673   unsigned long bg = bst->bg;
1674   /* ransom note */
1675   unsigned long fg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
1676                                           "ransomware.foreground2",
1677                                           "Ransomware.Foreground");
1678   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
1679                                           "ransomware.background2",
1680                                           "Ransomware.Background");
1681   /* buttons */
1682   unsigned long fg3 = get_pixel_resource (dpy, bst->xgwa.colormap,
1683                                           "ransomware.foreground3",
1684                                           "Ransomware.Foreground");
1685   unsigned long bg3 = get_pixel_resource (dpy, bst->xgwa.colormap,
1686                                           "ransomware.background3",
1687                                           "Ransomware.Background");
1688   /* links */
1689   unsigned long link = get_pixel_resource (dpy, bst->xgwa.colormap,
1690                                            "ransomware.link",
1691                                            "Ransomware.Foreground");
1692   /* headers */
1693   unsigned long theader = get_pixel_resource (dpy, bst->xgwa.colormap,
1694                                               "ransomware.timerheader",
1695                                               "Ransomware.Foreground");
1696   int left_column_width;
1697   int right_column_width;
1698   int right_column_height;
1699   int stage1_countdown_y, stage2_countdown_y;
1700   int margin;
1701   int top_height, bottom_height;
1702   int x, y;
1703
1704   if (bst->xgwa.width > 2560) n++;  /* Retina displays */
1705   for (i = 0; i < n; i++)
1706     {
1707       pixmap = double_pixmap (dpy, bst->xgwa.visual, bst->xgwa.depth,
1708                               pixmap, pix_w, pix_h);
1709       mask = double_pixmap (dpy, bst->xgwa.visual, 1,
1710                             mask, pix_w, pix_h);
1711       pix_w *= 2;
1712       pix_h *= 2;
1713     }
1714
1715   margin = line_height;
1716   left_column_width  = MAX (pix_w, line_height1 * 8);
1717   right_column_width = MIN (line_height * 40,
1718                             MAX (line_height * 8,
1719                                  bst->xgwa.width - left_column_width
1720                                  - margin*2));
1721   top_height = line_height * 2.5;
1722   bottom_height = line_height * 6;
1723   right_column_height = MIN (line_height * 36,
1724                              bst->xgwa.height - bottom_height - top_height
1725                              - line_height);
1726
1727   if ((bst->xgwa.width / 4) * 3 > bst->xgwa.height)
1728     /* Wide screen: keep the big text box at 4:3, centered. */
1729     right_column_height = MIN (right_column_height,
1730                                right_column_width * 4 / 3);
1731   else if (right_column_width < line_height * 30)
1732     /* Tall but narrow screen: make the text box be full height. */
1733     right_column_height = (bst->xgwa.height - bottom_height - top_height
1734                            - line_height);
1735
1736   x = (bst->xgwa.width - left_column_width - right_column_width - margin) / 2;
1737   y = (bst->xgwa.height - right_column_height - bottom_height) / 2;
1738
1739   bst->xoff = bst->left_margin = bst->right_margin = 0;
1740
1741   if (!(random() % 8))
1742     return apple2ransomware (dpy, window);
1743
1744   /* Draw the main red window */
1745   BSOD_INVERT (bst);
1746   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
1747
1748   if (pixmap) {
1749     bst->pixmap = pixmap;
1750     bst->mask = mask;
1751     BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h,
1752                  x + (left_column_width - pix_w) / 2,
1753                  y);
1754   }
1755
1756   /* Setup deadlines */
1757   strftime (stage1_deadline_str, sizeof(stage1_deadline_str),
1758             "%m/%d/%Y %H:%M:%S", localtime(&stage1_deadline));
1759   strftime (stage2_deadline_str, sizeof(stage1_deadline_str),
1760             "%m/%d/%Y %H:%M:%S", localtime(&stage2_deadline));
1761
1762   BSOD_INVERT (bst);
1763   /* Draw header pane */
1764   BSOD_FONT (bst, 0);
1765
1766   BSOD_MARGINS (bst,
1767                 x + left_column_width + margin,
1768                 bst->xgwa.width -
1769                 (x + left_column_width + margin + right_column_width));
1770   BSOD_MOVETO (bst, x + left_column_width + margin,
1771                y + bst->fontA->ascent);
1772   BSOD_COLOR (bst, fg, bg);
1773   BSOD_WORD_WRAP (bst);
1774   BSOD_TEXT (bst, CENTER, header_quip);
1775   BSOD_TRUNCATE (bst);
1776
1777   /* Draw left-side timers */
1778   BSOD_MARGINS (bst, x, bst->xgwa.width - (x + left_column_width));
1779   BSOD_MOVETO (bst, x, y + pix_h + line_height);
1780   BSOD_FONT (bst, 1);
1781
1782   BSOD_COLOR (bst, theader, bg);
1783   BSOD_TEXT (bst, CENTER, "Payment will be raised on\n");
1784   BSOD_COLOR (bst, fg, bg);
1785   BSOD_TEXT (bst, CENTER, stage1_deadline_str);
1786
1787   stage1_countdown_y = y + pix_h + line_height + line_height1 * 3;
1788   BSOD_MOVETO (bst, x, stage1_countdown_y - line_height);
1789   BSOD_TEXT (bst, CENTER, "Time Left");
1790
1791   BSOD_COLOR (bst, theader, bg);
1792   BSOD_WORD_WRAP (bst);
1793   BSOD_TEXT (bst, CENTER, "\n\n\n\nYour pixels will be lost on\n");
1794   BSOD_TRUNCATE (bst);
1795   BSOD_COLOR (bst, fg, bg);
1796   BSOD_TEXT (bst, CENTER, stage2_deadline_str);
1797
1798   stage2_countdown_y = stage1_countdown_y + line_height1 * 5;
1799   BSOD_MOVETO (bst, x, stage2_countdown_y - line_height);
1800   BSOD_TEXT (bst, CENTER, "Time Left");
1801
1802   BSOD_FONT (bst, 1);
1803
1804   /* Draw links, but skip on small screens */
1805   if (right_column_height > 425) {
1806     BSOD_MOVETO (bst, x, 
1807                  y + right_column_height + top_height + bottom_height
1808                  - line_height1 * 5);
1809     BSOD_COLOR (bst, link, bg);
1810     BSOD_TEXT (bst, LEFT, "\n");
1811     BSOD_TEXT (bst, LEFT, "About ");
1812     BSOD_TEXT (bst, LEFT, currency);
1813     BSOD_TEXT (bst, LEFT, "\n\n"
1814                           "How to buy ");
1815     BSOD_TEXT (bst, LEFT, currency);
1816     BSOD_TEXT (bst, LEFT, "\n\n"
1817                           "Contact us\n");
1818   }
1819
1820   /* Ransom note text area */
1821   BSOD_COLOR (bst, bg2, fg2);
1822   BSOD_RECT (bst, True, 
1823              x + left_column_width + margin,
1824              y + top_height,
1825              right_column_width,
1826              right_column_height);
1827   BSOD_MOVETO (bst,
1828                x + left_column_width + margin + line_height / 2,
1829                y + top_height + line_height + line_height / 2);
1830   BSOD_MARGINS (bst,
1831                 x + left_column_width + margin + line_height / 2,
1832                 bst->xgwa.width - 
1833                 (x + left_column_width + margin + right_column_width));
1834   BSOD_VERT_MARGINS (bst, 
1835                      y + top_height + line_height / 2,
1836                      bottom_height - line_height);
1837   BSOD_INVERT (bst);
1838
1839   /* Write out the ransom note itself */
1840   BSOD_CROP (bst, True);
1841   BSOD_WORD_WRAP (bst);
1842   for (i = 0; i < countof(lines); i++)
1843     {
1844       const char *s = lines[i];
1845       if (!strcmp(s, "[C]")) s = currency;
1846       else if  (!strcmp(s, "[Q]")) s = excuse_quip;
1847       else if  (!strcmp(s, "[S]")) s = screensaver_quip;
1848
1849       if (*s == '*')
1850         {
1851           s++;
1852           BSOD_FONT (bst, 2);
1853         }
1854       else
1855         BSOD_FONT (bst, 0);
1856
1857       BSOD_TEXT (bst, LEFT, s);
1858     }
1859   BSOD_TRUNCATE (bst);
1860   BSOD_CROP (bst, False);
1861   BSOD_FONT (bst, 0);
1862
1863   /* Draw over any overflowing ransom text. */
1864   BSOD_COLOR (bst, bg, fg);
1865   BSOD_RECT (bst, True,
1866              x + left_column_width + margin,
1867              y + top_height + right_column_height,
1868              bst->xgwa.width, bst->xgwa.height);
1869   BSOD_RECT (bst, True,
1870              x + left_column_width + margin + right_column_width,
1871              y + top_height,
1872              bst->xgwa.width, bst->xgwa.height);
1873
1874   /* Draw the footer */
1875   BSOD_COLOR (bst, theader, bg);
1876   BSOD_MOVETO (bst,
1877                x + left_column_width + margin,
1878                y + top_height + right_column_height + line_height * 2);
1879
1880   sprintf(buf, "Send $%.2f of %s to this address:\n", 101+frand(888), currency);
1881   BSOD_TEXT (bst, LEFT, buf);
1882   BSOD_COLOR (bst, fg2, bg2);
1883
1884   /* address, has some extra slashes in there because it's a fake address */
1885   for (i = 0; i < 40; i++) {
1886     const char *s =
1887       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123459789";
1888     buf[i] = s[random() % strlen(s)];
1889   }
1890   strncpy (buf, " //", 3);
1891   buf[10] = '/';
1892   buf[17] = '/';
1893   buf[24] = '/';
1894   strcpy (buf+33, " ");
1895   BSOD_TEXT (bst, LEFT, buf);
1896
1897   BSOD_COLOR (bst, fg, bg);
1898   BSOD_TEXT (bst, LEFT, "   ");
1899   BSOD_COLOR (bst, fg3, bg3);
1900   BSOD_TEXT (bst, LEFT, "  Copy  ");
1901   BSOD_COLOR (bst, fg, bg);
1902   BSOD_TEXT (bst, LEFT, "\n\n");
1903
1904   BSOD_COLOR (bst, fg3, bg3);
1905   BSOD_TEXT (bst, LEFT, "  Demogrify Screen  ");
1906   BSOD_COLOR (bst, fg, bg);
1907   BSOD_TEXT (bst, LEFT, "            ");
1908   BSOD_COLOR (bst, fg3, bg3);
1909   BSOD_TEXT (bst, LEFT, "  Check Payment  ");
1910
1911
1912   /* Draw countdown timers */
1913   BSOD_COLOR (bst, fg, bg);
1914   BSOD_FONT (bst, 0);
1915   do {
1916     /* First timer */
1917     BSOD_MOVETO (bst, x, stage1_countdown_y);
1918     BSOD_MARGINS (bst, x, bst->xgwa.width - (x + left_column_width));
1919
1920     countdown_r = stage1_deadline - now;
1921     countdown_s = countdown_r % 60;
1922     countdown_m = (countdown_r / 60) % 60;
1923     countdown_h = (countdown_r / 3600) % 24;
1924     countdown_d = (countdown_r / 86400);
1925
1926     sprintf (countdown_str, "%02d:%02d:%02d:%02d\n",
1927              countdown_d, countdown_h, countdown_m, countdown_s);
1928
1929     BSOD_TEXT (bst, CENTER, countdown_str);
1930
1931     /* Second timer */
1932     BSOD_MOVETO (bst, x, stage2_countdown_y);
1933
1934     countdown_r = stage2_deadline - now;
1935     countdown_s = countdown_r % 60;
1936     countdown_m = (countdown_r / 60) % 60;
1937     countdown_h = (countdown_r / 3600) % 24;
1938     countdown_d = (countdown_r / 86400);
1939
1940     sprintf (countdown_str, "%02d:%02d:%02d:%02d\n",
1941              countdown_d, countdown_h, countdown_m, countdown_s);
1942
1943     BSOD_TEXT (bst, CENTER, countdown_str);
1944
1945     BSOD_PAUSE (bst, 1000000);
1946     now++;
1947
1948     /* While the "correct" thing to do is create enough of a script to fill the
1949      * stage2_deadline, this would be 7 days of "frames", which is quite a bit
1950      * of memory. Instead, only fill the buffer with 1 hour of frames, which is
1951      * enough to make the point before xscreensaver cycles us.
1952      */
1953   } while (stage1_deadline - now > 3600);
1954
1955   XClearWindow (dpy, window);
1956   return bst;
1957 }
1958
1959
1960 /* As seen in Portal 2.  By jwz.
1961  */
1962 static struct bsod_state *
1963 glados (Display *dpy, Window window)
1964 {
1965   struct bsod_state *bst = make_bsod_state (dpy, window, "glaDOS", "GlaDOS");
1966   const char * panicstr[] = {
1967     "\n",
1968     "MOLTEN CORE WARNING\n",
1969     "\n",
1970     "An operator error exception has occurred at FISSREAC0020093:09\n",
1971     "FISSREAC0020077:14 FISSREAC0020023:17 FISSREAC0020088:22\n",
1972     "neutron multiplication rate at spikevalue 99999999\n",
1973     "\n",
1974     "* Press any key to vent radiological emissions into atmosphere.\n",
1975     "* Consult reactor core manual for instructions on proper reactor core\n",
1976     "maintenance and repair.\n",
1977     "\n",
1978     "Press any key to continue\n",
1979   };
1980
1981   int i;
1982
1983   bst->xoff = bst->left_margin = bst->right_margin = 0;
1984
1985   bst->y = ((bst->xgwa.height - bst->yoff -
1986              ((bst->font->ascent + bst->font->descent) * countof(panicstr)))
1987             / 2);
1988
1989   BSOD_MOVETO (bst, 0, bst->y);
1990   BSOD_INVERT (bst);
1991   BSOD_TEXT   (bst,  CENTER, "OPERATOR ERROR\n");
1992   BSOD_INVERT (bst);
1993   for (i = 0; i < countof(panicstr); i++)
1994     BSOD_TEXT (bst, CENTER, panicstr[i]);
1995   BSOD_PAUSE (bst, 1000000);
1996   BSOD_INVERT (bst);
1997   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
1998   BSOD_INVERT (bst);
1999   BSOD_PAUSE (bst, 250000);
2000   BSOD_RESET (bst);
2001
2002   XClearWindow (dpy, window);
2003   return bst;
2004 }
2005
2006
2007
2008 /* SCO OpenServer 5 panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
2009  */
2010 static struct bsod_state *
2011 sco (Display *dpy, Window window)
2012 {
2013   struct bsod_state *bst = make_bsod_state (dpy, window, "sco", "SCO");
2014
2015   BSOD_TEXT (bst, LEFT,
2016      "Unexpected trap in kernel mode:\n"
2017      "\n"
2018      "cr0 0x80010013     cr2  0x00000014     cr3 0x00000000  tlb  0x00000000\n"
2019      "ss  0x00071054    uesp  0x00012055     efl 0x00080888  ipl  0x00000005\n"
2020      "cs  0x00092585     eip  0x00544a4b     err 0x004d4a47  trap 0x0000000E\n"
2021      "eax 0x0045474b     ecx  0x0042544b     edx 0x57687920  ebx  0x61726520\n"
2022      "esp 0x796f7520     ebp  0x72656164     esi 0x696e6720  edi  0x74686973\n"
2023      "ds  0x3f000000     es   0x43494c48     fs  0x43525343  gs   0x4f4d4b53\n"
2024      "\n"
2025      "PANIC: k_trap - kernel mode trap type 0x0000000E\n"
2026      "Trying to dump 5023 pages to dumpdev hd (1/41), 63 pages per '.'\n"
2027     );
2028   BSOD_CHAR_DELAY (bst, 100000);
2029   BSOD_TEXT (bst, LEFT,
2030     "................................................................."
2031     "..............\n"
2032     );
2033   BSOD_CHAR_DELAY (bst, 0);
2034   BSOD_TEXT (bst, LEFT,
2035      "5023 pages dumped\n"
2036      "\n"
2037      "\n"
2038      );
2039   BSOD_PAUSE (bst, 2000000);
2040   BSOD_TEXT (bst, LEFT,
2041      "**   Safe to Power Off   **\n"
2042      "           - or -\n"
2043      "** Press Any Key to Reboot **\n"
2044     );
2045
2046   bst->y = ((bst->xgwa.height - bst->yoff -
2047              ((bst->font->ascent + bst->font->descent) * 18)));
2048
2049   XClearWindow (dpy, window);
2050   return bst;
2051 }
2052
2053
2054 /* Linux (sparc) panic, by Tom Kelly <tom@ancilla.toronto.on.ca>
2055  */
2056 static struct bsod_state *
2057 sparc_linux (Display *dpy, Window window)
2058 {
2059   struct bsod_state *bst = make_bsod_state (dpy, window,
2060                                             "sparclinux", "SparcLinux");
2061   bst->scroll_p = True;
2062   bst->y = bst->xgwa.height - bst->yoff
2063     - bst->font->ascent - bst->font->descent;
2064
2065   BSOD_TEXT (bst, LEFT,
2066         "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
2067         "Unable to handle kernel paging request at virtual address f0d4a000\n"
2068         "tsk->mm->context = 00000014\n"
2069         "tsk->mm->pgd = f26b0000\n"
2070         "              \\|/ ____ \\|/\n"
2071         "              \"@'/ ,. \\`@\"\n"
2072         "              /_| \\__/ |_\\\n"
2073         "                 \\__U_/\n"
2074         "gawk(22827): Oops\n"
2075         "PSR: 044010c1 PC: f001c2cc NPC: f001c2d0 Y: 00000000\n"
2076         "g0: 00001000 g1: fffffff7 g2: 04401086 g3: 0001eaa0\n"
2077         "g4: 000207dc g5: f0130400 g6: f0d4a018 g7: 00000001\n"
2078         "o0: 00000000 o1: f0d4a298 o2: 00000040 o3: f1380718\n"
2079         "o4: f1380718 o5: 00000200 sp: f1b13f08 ret_pc: f001c2a0\n"
2080         "l0: efffd880 l1: 00000001 l2: f0d4a230 l3: 00000014\n"
2081         "l4: 0000ffff l5: f0131550 l6: f012c000 l7: f0130400\n"
2082         "i0: f1b13fb0 i1: 00000001 i2: 00000002 i3: 0007c000\n"
2083         "i4: f01457c0 i5: 00000004 i6: f1b13f70 i7: f0015360\n"
2084         "Instruction DUMP:\n"
2085     );
2086
2087   XClearWindow (dpy, window);
2088   return bst;
2089 }
2090
2091
2092 /* BSD Panic by greywolf@starwolf.com - modeled after the Linux panic above.
2093    By Grey Wolf <greywolf@siteROCK.com>
2094  */
2095 static struct bsod_state *
2096 bsd (Display *dpy, Window window)
2097 {
2098   struct bsod_state *bst = make_bsod_state (dpy, window, "bsd", "BSD");
2099
2100   const char * const panicstr[] = {
2101     "panic: ifree: freeing free inode\n",
2102     "panic: blkfree: freeing free block\n",
2103     "panic: improbability coefficient below zero\n",
2104     "panic: cgsixmmap\n",
2105     "panic: crazy interrupts\n",
2106     "panic: nmi\n",
2107     "panic: attempted windows install\n",
2108     "panic: don't\n",
2109     "panic: free inode isn't\n",
2110     "panic: cpu_fork: curproc\n",
2111     "panic: malloc: out of space in kmem_map\n",
2112     "panic: vogon starship detected\n",
2113     "panic: teleport chamber: out of order\n",
2114     "panic: Brain fried - core dumped\n"
2115    };
2116   int i, n, b;
2117   char syncing[80], bbuf[5];
2118
2119   for (i = 0; i < sizeof(syncing); i++)
2120     syncing[i] = 0;
2121
2122   i = (random() % (sizeof(panicstr) / sizeof(*panicstr)));
2123   BSOD_TEXT (bst, LEFT, panicstr[i]);
2124   BSOD_TEXT (bst, LEFT, "Syncing disks: ");
2125
2126   b = (random() % 40);
2127   for (n = 0; (n < 20) && (b > 0); n++)
2128     {
2129       if (i)
2130         {
2131           i = (random() & 0x7);
2132           b -= (random() & 0xff) % 20;
2133           if (b < 0)
2134             b = 0;
2135         }
2136       sprintf (bbuf, "%d ", b);
2137       BSOD_TEXT (bst, LEFT, bbuf);
2138       BSOD_PAUSE (bst, 1000000);
2139     }
2140
2141   BSOD_TEXT (bst, LEFT, "\n");
2142   BSOD_TEXT (bst, LEFT, (b ? "damn!" : "sunk!"));
2143   BSOD_TEXT (bst, LEFT, "\nRebooting\n");
2144
2145   bst->y = ((bst->xgwa.height - bst->yoff -
2146              ((bst->font->ascent + bst->font->descent) * 4)));
2147
2148   XClearWindow (dpy, window);
2149   return bst;
2150 }
2151
2152
2153 static struct bsod_state *
2154 amiga (Display *dpy, Window window)
2155 {
2156   struct bsod_state *bst = make_bsod_state (dpy, window, "amiga", "Amiga");
2157
2158   const char *guru1 ="Software failure.  Press left mouse button to continue.";
2159   const char *guru2 ="Guru Meditation #00000003.00C01570";
2160   Pixmap pixmap = 0;
2161   Pixmap mask = 0;
2162   int pix_w = 0, pix_h = 0;
2163   int height;
2164   int lw = bst->font->ascent + bst->font->descent;
2165   unsigned long fg = bst->fg;
2166   unsigned long bg = bst->bg;
2167
2168   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
2169                                           "amiga.background2",
2170                                           "Amiga.Background");
2171
2172   bst->yoff = 0;
2173   bst->top_margin = bst->bottom_margin = 0;
2174
2175   pixmap = image_data_to_pixmap (dpy, window,
2176                                  amiga_png, sizeof(amiga_png),
2177                                  &pix_w, &pix_h, &mask);
2178
2179   if (pixmap)
2180     {
2181       int i, n = 0;
2182       if (MIN (bst->xgwa.width, bst->xgwa.height) > 600) n++;
2183       if (bst->xgwa.width > 2560) n++;  /* Retina displays */
2184       for (i = 0; i < n; i++)
2185         {
2186           pixmap = double_pixmap (dpy, bst->xgwa.visual, bst->xgwa.depth,
2187                                   pixmap, pix_w, pix_h);
2188           mask = double_pixmap (dpy, bst->xgwa.visual, 1, mask, pix_w, pix_h);
2189           pix_w *= 2;
2190           pix_h *= 2;
2191         }
2192     }
2193
2194   XSetLineAttributes (dpy, bst->gc, lw, LineSolid, CapButt, JoinMiter);
2195
2196   height = lw * 5;
2197
2198   bst->char_delay = bst->line_delay = 0;
2199
2200   BSOD_PAUSE (bst, 2000000);
2201   BSOD_COPY (bst, 0, 0, bst->xgwa.width, bst->xgwa.height - height, 0, height);
2202
2203   BSOD_COLOR (bst, fg, bg);
2204   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, height); /* red */
2205   BSOD_COLOR (bst, bg, fg);
2206   BSOD_RECT (bst, True, lw/2, lw/2, bst->xgwa.width-lw, height-lw); /* black */
2207   BSOD_COLOR (bst, fg, bg);
2208   BSOD_MOVETO (bst, 0, lw*2);
2209   BSOD_TEXT (bst, CENTER, guru1);
2210   BSOD_MOVETO (bst, 0, lw*3.5);
2211   BSOD_TEXT (bst, CENTER, guru2);
2212   BSOD_PAUSE (bst, 1000000);
2213
2214   BSOD_COLOR (bst, bg, fg);
2215   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, height); /* black */
2216   BSOD_COLOR (bst, fg, bg);
2217   BSOD_MOVETO (bst, 0, lw*2);
2218   BSOD_TEXT (bst, CENTER, guru1);
2219   BSOD_MOVETO (bst, 0, lw*3.5);
2220   BSOD_TEXT (bst, CENTER, guru2);
2221   BSOD_PAUSE (bst, 1000000);
2222
2223   BSOD_LOOP (bst, -17);
2224
2225   XSetWindowBackground (dpy, window, bg2);
2226   XClearWindow (dpy, window);
2227   XSetWindowBackground (dpy, window, bst->bg);
2228
2229   if (pixmap)
2230     {
2231       int x = (bst->xgwa.width - pix_w) / 2;
2232       int y = ((bst->xgwa.height - pix_h) / 2);
2233       XSetClipMask (dpy, bst->gc, mask);
2234       XSetClipOrigin (dpy, bst->gc, x, y);
2235       XCopyArea (dpy, pixmap, bst->window, bst->gc, 0, 0, pix_w, pix_h, x, y);
2236       XSetClipMask (dpy, bst->gc, None);
2237       XFreePixmap (dpy, pixmap);
2238       XFreePixmap (dpy, mask);
2239     }
2240
2241   bst->y += lw;
2242
2243   return bst;
2244 }
2245
2246
2247
2248 /* Atari ST, by Marcus Herbert <rhoenie@nobiscum.de>
2249    Marcus had this to say:
2250
2251         Though I still have my Atari somewhere, I hardly remember
2252         the meaning of the bombs. I think 9 bombs was "bus error" or
2253         something like that.  And you often had a few bombs displayed
2254         quickly and then the next few ones coming up step by step.
2255         Perhaps somebody else can tell you more about it..  its just
2256         a quick hack :-}
2257  */
2258 static struct bsod_state *
2259 atari (Display *dpy, Window window)
2260 {
2261   struct bsod_state *bst = make_bsod_state (dpy, window, "atari", "Atari");
2262
2263   int pix_w, pix_h;
2264   int offset;
2265   int i, x, y;
2266   Pixmap mask = 0;
2267   Pixmap pixmap = image_data_to_pixmap (dpy, window,
2268                                         atari_png, sizeof(atari_png),
2269                                         &pix_w, &pix_h, &mask);
2270
2271   pixmap = double_pixmap (dpy, bst->xgwa.visual, bst->xgwa.depth,
2272                           pixmap, pix_w, pix_h);
2273   mask = double_pixmap (dpy, bst->xgwa.visual, 1, mask, pix_w, pix_h);
2274   pix_w *= 2;
2275   pix_h *= 2;
2276
2277   offset = pix_w;
2278   x = 0;
2279   y = bst->xgwa.height/2;
2280   if (y < 0) y = 0;
2281
2282   for (i = 1; i< 7; i++)
2283     BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y);
2284
2285   for (; i< 10; i++)
2286     {
2287       BSOD_PAUSE (bst, 1000000);
2288       BSOD_COPY (bst, x, y, pix_w, pix_h, (x + (i*offset)), y);
2289     }
2290
2291   XClearWindow (dpy, window);
2292   XSetClipMask (dpy, bst->gc, mask);
2293   XSetClipOrigin (dpy, bst->gc, x, y);
2294   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
2295   XSetClipMask (dpy, bst->gc, None);
2296   XFreePixmap (dpy, pixmap);
2297   XFreePixmap (dpy, mask);
2298
2299   return bst;
2300 }
2301
2302
2303 static struct bsod_state *
2304 mac (Display *dpy, Window window)
2305 {
2306   struct bsod_state *bst = make_bsod_state (dpy, window, "mac", "Mac");
2307
2308   int pix_w, pix_h;
2309   int i;
2310
2311   const char *string = ("0 0 0 0 0 0 0 F\n"
2312                         "0 0 0 0 0 0 0 3");
2313
2314   Pixmap mask = 0;
2315   Pixmap pixmap = image_data_to_pixmap (dpy, window,
2316                                         mac_png, sizeof(mac_png),
2317                                         &pix_w, &pix_h, &mask);
2318   int offset = pix_h * 4;
2319
2320   bst->xoff = bst->left_margin = bst->right_margin = 0;
2321
2322   for (i = 0; i < 2; i++)
2323     {
2324       pixmap = double_pixmap (dpy, bst->xgwa.visual, bst->xgwa.depth,
2325                               pixmap, pix_w, pix_h);
2326       mask = double_pixmap (dpy, bst->xgwa.visual, 1, mask, pix_w, pix_h);
2327       pix_w *= 2; pix_h *= 2;
2328     }
2329
2330   bst->x = (bst->xgwa.width - pix_w) / 2;
2331   bst->y = (((bst->xgwa.height + offset) / 2) -
2332             pix_h -
2333             (bst->font->ascent + bst->font->descent) * 2);
2334   if (bst->y < 0) bst->y = 0;
2335
2336   XClearWindow (dpy, window);
2337   XSetClipMask (dpy, bst->gc, mask);
2338   XSetClipOrigin (dpy, bst->gc, bst->x, bst->y);
2339   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, bst->x, bst->y);
2340   XSetClipMask (dpy, bst->gc, None);
2341   XFreePixmap (dpy, pixmap);
2342   XFreePixmap (dpy, mask);
2343
2344   bst->y += offset + bst->font->ascent + bst->font->descent;
2345   BSOD_TEXT (bst, CENTER, string);
2346
2347   return bst;
2348 }
2349
2350
2351 static struct bsod_state *
2352 macsbug (Display *dpy, Window window)
2353 {
2354   struct bsod_state *bst = make_bsod_state (dpy, window, "macsbug", "MacsBug");
2355
2356   __extension__
2357   const char *left = ("    SP     \n"
2358                       " 04EB0A58  \n"
2359                       "58 00010000\n"
2360                       "5C 00010000\n"
2361                       "   ........\n"
2362                       "60 00000000\n"
2363                       "64 000004EB\n"
2364                       "   ........\n"
2365                       "68 0000027F\n"
2366                       "6C 2D980035\n"
2367                       "   ....-..5\n"
2368                       "70 00000054\n"
2369                       "74 0173003E\n"
2370                       "   ...T.s.>\n"
2371                       "78 04EBDA76\n"
2372                       "7C 04EBDA8E\n"
2373                       "   .S.L.a.U\n"
2374                       "80 00000000\n"
2375                       "84 000004EB\n"
2376                       "   ........\n"
2377                       "88 00010000\n"
2378                       "8C 00010000\n"
2379                       "   ...{3..S\n"
2380                       "\n"
2381                       "\n"
2382                       " CurApName \n"
2383                       "  Finder   \n"
2384                       "\n"
2385                       " 32-bit VM \n"
2386                       "SR Smxnzvc0\n"
2387                       "D0 04EC0062\n"
2388                       "D1 00000053\n"
2389                       "D2 FFFF0100\n"
2390                       "D3 00010000\n"
2391                       "D4 00010000\n"
2392                       "D5 04EBDA76\n"
2393                       "D6 04EBDA8E\n"
2394                       "D7 00000001\n"
2395                       "\n"
2396                       "A0 04EBDA76\n"
2397                       "A1 04EBDA8E\n"
2398                       "A2 A0A00060\n"
2399                       "A3 027F2D98\n"
2400                       "A4 027F2E58\n"
2401                       "A5 04EC04F0\n"
2402                       "A6 04EB0A86\n"
2403                       "A7 04EB0A58");
2404   const char *bottom = ("  _A09D\n"
2405                         "     +00884    40843714     #$0700,SR         "
2406                         "                  ; A973        | A973\n"
2407                         "     +00886    40843765     *+$0400           "
2408                         "                                | 4A1F\n"
2409                         "     +00888    40843718     $0004(A7),([0,A7[)"
2410                         "                  ; 04E8D0AE    | 66B8");
2411   __extension__
2412   const char * body = ("PowerPC unmapped memory exception at 003AFDAC "
2413                                                 "BowelsOfTheMemoryMgr+04F9C\n"
2414                       " Calling chain using A6/R1 links\n"
2415                       "  Back chain  ISA  Caller\n"
2416                       "  00000000    PPC  28C5353C  __start+00054\n"
2417                       "  24DB03C0    PPC  28B9258C  main+0039C\n"
2418                       "  24DB0350    PPC  28B9210C  MainEvent+00494\n"
2419                       "  24DB02B0    PPC  28B91B40  HandleEvent+00278\n"
2420                       "  24DB0250    PPC  28B83DAC  DoAppleEvent+00020\n"
2421                       "  24DB0210    PPC  FFD3E5D0  "
2422                                                 "AEProcessAppleEvent+00020\n"
2423                       "  24DB0132    68K  00589468\n"
2424                       "  24DAFF8C    68K  00589582\n"
2425                       "  24DAFF26    68K  00588F70\n"
2426                       "  24DAFEB3    PPC  00307098  "
2427                                                 "EmToNatEndMoveParams+00014\n"
2428                       "  24DAFE40    PPC  28B9D0B0  DoScript+001C4\n"
2429                       "  24DAFDD0    PPC  28B9C35C  RunScript+00390\n"
2430                       "  24DAFC60    PPC  28BA36D4  run_perl+000E0\n"
2431                       "  24DAFC10    PPC  28BC2904  perl_run+002CC\n"
2432                       "  24DAFA80    PPC  28C18490  Perl_runops+00068\n"
2433                       "  24DAFA30    PPC  28BE6CC0  Perl_pp_backtick+000FC\n"
2434                       "  24DAF9D0    PPC  28BA48B8  Perl_my_popen+00158\n"
2435                       "  24DAF980    PPC  28C5395C  sfclose+00378\n"
2436                       "  24DAF930    PPC  28BA568C  free+0000C\n"
2437                       "  24DAF8F0    PPC  28BA6254  pool_free+001D0\n"
2438                       "  24DAF8A0    PPC  FFD48F14  DisposePtr+00028\n"
2439                       "  24DAF7C9    PPC  00307098  "
2440                                                 "EmToNatEndMoveParams+00014\n"
2441                       "  24DAF780    PPC  003AA180  __DisposePtr+00010");
2442
2443   const char *s;
2444   int body_lines = 1;
2445
2446   int char_width, line_height;
2447   int col_right, row_top, row_bottom, page_right, page_bottom, body_top;
2448   int xoff, yoff;
2449
2450   unsigned long fg = bst->fg;
2451   unsigned long bg = bst->bg;
2452   unsigned long bc = get_pixel_resource (dpy, bst->xgwa.colormap,
2453                                          "macsbug.borderColor",
2454                                          "MacsBug.BorderColor");
2455
2456   bst->xoff = bst->left_margin = bst->right_margin = 0;
2457
2458   for (s = body; *s; s++) if (*s == '\n') body_lines++;
2459
2460   char_width = (bst->font->per_char
2461                 ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
2462                 : bst->font->min_bounds.width);
2463   line_height = bst->font->ascent + bst->font->descent;
2464
2465   col_right   = char_width  * 12;  /* number of columns in `left' */
2466   page_bottom = line_height * 47;  /* number of lines in `left'   */
2467
2468   if (page_bottom > bst->xgwa.height - bst->yoff)
2469     page_bottom = bst->xgwa.height - bst->yoff;
2470
2471   row_bottom = page_bottom - line_height;
2472   row_top    = row_bottom - (line_height * 4);
2473   page_right = col_right + (char_width * 88);
2474   body_top   = row_top - (line_height * body_lines);
2475
2476   page_bottom += 2;
2477   row_bottom += 2;
2478   body_top -= 4;
2479
2480   if (body_top > 4)
2481     body_top = 4;
2482
2483   xoff = (bst->xgwa.width  - page_right)  / 2;
2484   yoff = (bst->xgwa.height - page_bottom) / 2;
2485
2486   if (xoff < 0) xoff = 0;
2487   if (yoff < 0) yoff = 0;
2488
2489   BSOD_MARGINS (bst, xoff, yoff);
2490
2491   BSOD_COLOR (bst, bc, bg);
2492   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
2493   BSOD_COLOR (bst, bg, bg);
2494   BSOD_RECT (bst, True, xoff-2, yoff, page_right+4, page_bottom);
2495   BSOD_COLOR (bst, fg, bg);
2496
2497   BSOD_MOVETO (bst, xoff, yoff + line_height);
2498   BSOD_TEXT (bst, LEFT, left);
2499   BSOD_MOVETO (bst, xoff+col_right, yoff + row_top + line_height);
2500   BSOD_TEXT (bst, LEFT, bottom);
2501
2502   BSOD_RECT (bst, True, xoff + col_right, yoff, 2, page_bottom);
2503   BSOD_RECT (bst, True, xoff + col_right, yoff + row_top,
2504              page_right - col_right, 1);
2505   BSOD_RECT (bst, True, xoff + col_right, yoff + row_bottom,
2506              page_right - col_right, 1);
2507   BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom);
2508
2509   BSOD_LINE_DELAY (bst, 500);
2510   BSOD_MOVETO (bst,
2511                xoff + col_right + char_width,
2512                yoff + body_top + line_height);
2513   BSOD_MARGINS (bst, xoff + col_right + char_width, yoff);
2514   BSOD_TEXT (bst, LEFT, body);
2515
2516   BSOD_RECT (bst, False, xoff-2, yoff, page_right+4, page_bottom); /* again */
2517
2518   BSOD_RECT (bst, False,
2519              xoff + col_right + (char_width/2)+2,
2520              yoff + row_bottom + 2,
2521              0,
2522              page_bottom - row_bottom - 4);
2523
2524   BSOD_PAUSE (bst, 666666);
2525   BSOD_INVERT (bst);
2526   BSOD_LOOP (bst, -3);
2527
2528   XClearWindow (dpy, window);
2529   return bst;
2530 }
2531
2532
2533 static struct bsod_state *
2534 mac1 (Display *dpy, Window window)
2535 {
2536   struct bsod_state *bst = make_bsod_state (dpy, window, "mac1", "Mac1");
2537
2538   int pix_w, pix_h;
2539   int x, y;
2540   Pixmap mask = 0;
2541   Pixmap pixmap = image_data_to_pixmap (dpy, window,
2542                                         macbomb_png, sizeof(macbomb_png),
2543                                         &pix_w, &pix_h, &mask);
2544
2545   if (pixmap && 
2546       pix_w < bst->xgwa.width / 2 &&
2547       pix_h < bst->xgwa.height / 2)
2548     {
2549       int i, n = 1;
2550       if (bst->xgwa.width > 2560) n++;  /* Retina displays */
2551       for (i = 0; i < n; i++)
2552         {
2553           pixmap = double_pixmap (dpy, bst->xgwa.visual,
2554                                   bst->xgwa.depth, pixmap, pix_w, pix_h);
2555           mask = double_pixmap (dpy, bst->xgwa.visual, 1, mask, pix_w, pix_h);
2556           pix_w *= 2;
2557           pix_h *= 2;
2558         }
2559     }
2560
2561   x = (bst->xgwa.width - pix_w) / 2;
2562   y = (bst->xgwa.height - pix_h) / 2;
2563   if (y < 0) y = 0;
2564
2565   XClearWindow (dpy, window);
2566   XSetClipMask (dpy, bst->gc, mask);
2567   XSetClipOrigin (dpy, bst->gc, x, y);
2568   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
2569   XSetClipMask (dpy, bst->gc, None);
2570   XFreePixmap (dpy, mask);
2571
2572   return bst;
2573 }
2574
2575
2576 /* This is what kernel panics looked like on MacOS X 10.0 through 10.1.5.
2577    In later releases, it's a graphic of a power button with text in
2578    English, French, German, and Japanese overlayed transparently.
2579  */
2580 static struct bsod_state *
2581 macx_10_0 (Display *dpy, Window window)
2582 {
2583   struct bsod_state *bst = make_bsod_state (dpy, window, "macx", "MacX");
2584
2585   XClearWindow (dpy, window);
2586   XSetForeground (dpy, bst->gc,
2587                   get_pixel_resource (dpy, bst->xgwa.colormap,
2588                                       "macx.textForeground",
2589                                       "MacX.TextForeground"));
2590   XSetBackground (dpy, bst->gc,
2591                   get_pixel_resource (dpy, bst->xgwa.colormap,
2592                                       "macx.textBackground",
2593                                       "MacX.TextBackground"));
2594
2595   {
2596     Pixmap pixmap = 0;
2597     Pixmap mask = 0;
2598     int x, y, pix_w, pix_h;
2599     pixmap = image_data_to_pixmap (dpy, window,
2600                                    hmac_png, sizeof(hmac_png),
2601                                    &pix_w, &pix_h, &mask);
2602
2603 # ifdef HAVE_MOBILE
2604     if (pixmap)
2605       {
2606         pixmap = double_pixmap (dpy, bst->xgwa.visual,
2607                                 bst->xgwa.depth, pixmap, pix_w, pix_h);
2608         mask = double_pixmap (dpy, bst->xgwa.visual,
2609                               1, mask, pix_w, pix_h);
2610         pix_w *= 2;
2611         pix_h *= 2;
2612       }
2613 # endif
2614
2615     x = (bst->xgwa.width - pix_w) / 2;
2616     y = (bst->xgwa.height - pix_h) / 2;
2617     if (y < 0) y = 0;
2618     XSetClipMask (dpy, bst->gc, mask);
2619     XSetClipOrigin (dpy, bst->gc, x, y);
2620     XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
2621     XSetClipMask (dpy, bst->gc, None);
2622     XFreePixmap (dpy, pixmap);
2623     XFreePixmap (dpy, mask);
2624   }
2625
2626   bst->left_margin = 0;
2627   bst->right_margin = 0;
2628   bst->y = bst->font->ascent;
2629   bst->macx_eol_kludge = True;
2630   bst->wrap_p = True;
2631
2632   BSOD_PAUSE (bst, 3000000);
2633   BSOD_TEXT (bst, LEFT,
2634     "panic(cpu 0): Unable to find driver for this platform: "
2635     "\"PowerMac 3,5\".\n"
2636     "\n"
2637     "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
2638     "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
2639     "\n"
2640     "\n"
2641     "\n"
2642     "No debugger configured - dumping debug information\n"
2643     "\n"
2644     "version string : Darwin Kernel Version 1.3:\n"
2645     "Thu Mar  1 06:56:40 PST 2001; root:xnu/xnu-123.5.obj~1/RELEASE_PPC\n"
2646     "\n"
2647     "\n"
2648     "\n"
2649     "\n"
2650     "DBAT0: 00000000 00000000\n"
2651     "DBAT1: 00000000 00000000\n"
2652     "DBAT2: 80001FFE 8000003A\n"
2653     "DBAT3: 90001FFE 9000003A\n"
2654     "MSR=00001030\n"
2655     "backtrace: 0x0008c2f4 0x0002a7a0 0x001f0204 0x001d4e4c 0x001d4c5c "
2656     "0x001a56cc 0x01d5dbc 0x001c621c 0x00037430 0x00037364\n"
2657     "\n"
2658     "panic: We are hanging here...\n");
2659
2660   return bst;
2661 }
2662
2663
2664 static struct bsod_state *
2665 macx_10_2 (Display *dpy, Window window, Bool v10_3_p)
2666 {
2667   struct bsod_state *bst = make_bsod_state (dpy, window, "macx", "MacX");
2668
2669   Pixmap mask = 0;
2670   Pixmap pixmap = 0;
2671   int pix_w = 0, pix_h = 0;
2672   int x, y;
2673
2674   if (v10_3_p)
2675     pixmap = image_data_to_pixmap (dpy, window,
2676                                    osx_10_3_png, sizeof(osx_10_3_png),
2677                                    &pix_w, &pix_h, &mask);
2678   else
2679     pixmap = image_data_to_pixmap (dpy, window,
2680                                    osx_10_2_png, sizeof(osx_10_2_png),
2681                                    &pix_w, &pix_h, &mask);
2682   if (! pixmap) abort();
2683   if (! mask) abort();
2684
2685 #if 0
2686   if (bst->xgwa.height > 600)   /* scale up the bitmap */
2687     {
2688       pixmap = double_pixmap (dpy, bst->xgwa.visual, bst->xgwa.depth,
2689                               pixmap, pix_w, pix_h);
2690       mask = double_pixmap (dpy, bst->xgwa.visual, 1, mask, pix_w, pix_h);
2691       if (! pixmap) abort();
2692       if (! mask) abort();
2693       pix_w *= 2;
2694       pix_h *= 2;
2695     }
2696 #endif
2697
2698   BSOD_IMG (bst);
2699   BSOD_PAUSE (bst, 2000000);
2700
2701   bst->pixmap = pixmap;
2702   bst->mask = mask;
2703
2704   x = (bst->xgwa.width - pix_w) / 2;
2705   y = ((bst->xgwa.height - pix_h) / 2);
2706   BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, x, y);
2707
2708   return bst;
2709 }
2710
2711
2712 /* 2006 Mac Mini with MacOS 10.6 failing with a bad boot drive. By jwz.
2713  */
2714 static struct bsod_state *
2715 mac_diskfail (Display *dpy, Window window)
2716 {
2717   struct bsod_state *bst = make_bsod_state (dpy, window, "macdisk", "Mac");
2718   int cw = (bst->font->per_char
2719             ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
2720             : bst->font->min_bounds.width);
2721   int h = bst->font->ascent + bst->font->descent;
2722   int L = (bst->xgwa.width - (cw * 80)) / 2;
2723   int T = (bst->xgwa.height - (h  * 10)) / 2;
2724
2725   unsigned long fg = bst->fg;
2726   unsigned long bg = bst->bg;
2727   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
2728                                           "macx.background",
2729                                           "Mac.Background");
2730   if (L < 0) L = 0;
2731   if (T < 0) T = 0;
2732
2733   bst->wrap_p = True;
2734   bst->scroll_p = True;
2735
2736   BSOD_COLOR(bst, bg2, bg);
2737   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
2738   BSOD_PAUSE (bst, 3000000);
2739
2740   BSOD_COLOR(bst, bg, fg);
2741   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
2742   BSOD_COLOR(bst, fg, bg);
2743
2744   BSOD_MARGINS (bst, L, L);
2745   BSOD_MOVETO (bst, L, T);
2746
2747   BSOD_TEXT (bst, LEFT,
2748              "efiboot loaded from device: Acpi(PNP0A03,0)/Pci*1F|2)/Ata"
2749              "(Primary,Slave)/HD(Part\n"
2750              "2,Sig8997E427-064E-4FE7-8CB9-F27A784B232C)\n"
2751              "boot file path: \\System\\Library\\CoreServices\\boot.efi\n"
2752              ".Loading kernel cache file 'System\\Library\\Caches\\"
2753              "com.apple.kext.caches\\Startup\\\n"
2754              "kernelcache_i386.2A14EC2C'\n"
2755              "Loading 'mach_kernel'...\n"
2756              );
2757   BSOD_CHAR_DELAY (bst, 7000);
2758   BSOD_TEXT (bst, LEFT,
2759              ".....................\n"
2760              );
2761   BSOD_CHAR_DELAY (bst, 0);
2762   BSOD_TEXT (bst, LEFT,
2763              "root device uuid is 'B62181B4-6755-3C27-BFA1-49A0E053DBD6\n"
2764              "Loading drivers...\n"
2765              "Loading System\\Library\\Caches\\com.apple.kext.caches\\"
2766              "Startup\\Extensions.mkext....\n"
2767              );
2768   BSOD_CHAR_DELAY (bst, 7000);
2769   BSOD_TEXT (bst, LEFT,
2770              "..............................................................."
2771              ".................\n"
2772              "..............................................................."
2773              ".................\n"
2774              "..............\n"
2775              );
2776   BSOD_INVERT (bst);
2777   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
2778   BSOD_INVERT (bst);
2779
2780   BSOD_MARGINS (bst, 0, 0);
2781   BSOD_MOVETO (bst, 0, h);
2782
2783   BSOD_CHAR_DELAY (bst, 0);
2784   BSOD_LINE_DELAY (bst, 5000);
2785   BSOD_TEXT (bst, LEFT,
2786              "npvhash=4095\n"
2787              "PRE enabled\n"
2788              "Darwin Kernel Version 10.8.9: Tue Jun  7 16:33:36 PDT 2011;"
2789              " root:xnu-1504.15.3~1/RELEASE_I386\n"
2790              "vm_page_bootstrap: 508036 free pages and 16252 wired pages\n"
2791              "standard timeslicing quantum is 10000 us\n"
2792              "mig_table_max_displ = 73\n"
2793              "AppleACPICPU: ProcessorId=0 LocalApicId=0 Enabled\n"
2794              "AppleACPICPU: ProcessorId=1 LocalApicId=1 Enabled\n"
2795              "calling npo_policy_init for Quarantine\n"
2796              "Security policy loaded: Quaantine policy (Quarantine)\n"
2797              "calling npo_policy_init for Sandbox\n"
2798              "Security policy loaded: Seatbelt sandbox policy (Sandbox)\n"
2799              "calling npo_policy_init for TMSafetyNet\n"
2800              "Security policy loaded: Safety net for Time Machine "
2801              "(TMSafetyNet)\n"
2802              "Copyright (c) 1982, 1986, 1989, 1991, 1993\n"
2803              "The Regents of the University of California. All rights "
2804              "reserved.\n"
2805              "\n"
2806              "MAC Framework successfully initialized\n"
2807              "using 10485 buffer headers and 4096 cluster IO buffer headers\n"
2808              "IOAPIC: Version 0x20 Vectors 64:87\n"
2809              "ACPI: System State [S0 S3 S4 S5] (S3)\n"
2810              "PFM64 0x10000000, 0xf0000000\n"
2811              "[ PCI configuration begin ]\n"
2812              "PCI configuration changed (bridge=1 device=1 cardbus=0)\n"
2813              "[ PCI configuration end, bridges 4 devices 17 ]\n"
2814              "nbinit: done (64 MB memory set for nbuf pool)\n"
2815              "rooting via boot-uuid from /chosen: "
2816              "B62181B4-6755-3C27-BFA1-49A0E053DBD6\n"
2817              "Waiting on <dict ID=\"0\"><key>IOProviderClass</key>"
2818              "<string ID=\"1\">IOResources</string><key>IOResourceMatch</key>"
2819              "<string ID=\"2\">boot-uuid-nedia</string></dict>\n"
2820              "com.apple.AppleFSCCompressionTypeZlib kmod start\n"
2821              "com.apple.AppleFSCCompressionTypeZlib kmod succeeded\n"
2822              "AppleIntelCPUPowerManagementClient: ready\n"
2823              "FireWire (OHCI) Lucent ID 5811  built-in now active, GUID "
2824              "0019e3fffe97f8b4; max speed s400.\n"
2825              "Got boot device = IOService:/AppleACPIPlatformExpert/PCI000/"
2826              "AppleACPIPCI/SATA@1F,2/AppleAHCI/PRI202/IOAHCIDevice@0/"
2827              "AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/"
2828              "IOBlockStorageDriver/ST96812AS Media/IOGUIDPartitionScheme/"
2829              "Customer02\n"
2830              );
2831   BSOD_PAUSE (bst, 1000000);
2832   BSOD_TEXT (bst, LEFT,
2833              "BSD root: Disk0s, major 14, minor 2\n"
2834              "[Bluetooth::CSRHIDTransition] switchtoHCIMode (legacy)\n"
2835              "[Bluetooth::CSRHIDTransition] transition complete.\n"
2836              "CSRUSBBluetoothHCIController::setupHardware super returned 0\n"
2837              );
2838   BSOD_PAUSE (bst, 3000000);
2839   BSOD_TEXT (bst, LEFT,
2840              "disk0s2: I/O error.\n"
2841              "0 [Level 3] [ReadUID 0] [Facility com.apple.system.fs] "
2842              "[ErrType IO] [ErrNo 5] [IOType Read] [PBlkNum 48424] "
2843              "[LBlkNum 1362] [FSLogMsgID 2009724291] [FSLogMsgOrder First]\n"
2844              "0 [Level 3] [ReadUID 0] [Facility com.apple.system.fs] "
2845              "[DevNode root_device] [MountPt /] [FSLogMsgID 2009724291] "
2846              "[FSLogMsgOrder Last]\n"
2847              "panic(cpu 0 caller 0x47f5ad): \"Process 1 exec of /sbin/launchd"
2848              " failed, errno 5\\n\"0/SourceCache/xnu/xnu-1504.15.3/bsd/kern/"
2849              "kern_exec.c:3145\n"
2850              "Debugger called: <panic>\n"
2851              "Backtrace (CPU 0), Frame : Return Address (4 potential args "
2852              "on stack)\n"
2853              "0x34bf3e48 : 0x21b837 (0x5dd7fc 0x34bf3e7c 0x223ce1 0x0)\n"
2854              "0x34bf3e98 : 0x47f5ad (0x5cf950 0x831c08 0x5 0x0)\n"
2855              "0x34bf3ef8 : 0x4696d2 (0x4800d20 0x1fe 0x45a69a0 0x80000001)\n"
2856              "0x34bf3f38 : 0x48fee5 (0x46077a8 0x84baa0 0x34bf3f88 "
2857              "0x34bf3f94)\n"
2858              "0x34bf3f68 : 0x219432 (0x46077a8 0xffffff7f 0x0 0x227c4b)\n"
2859              "0x34bf3fa8 : 0x2aacb4 (0xffffffff 0x1 0x22f8f5 0x227c4b)\n"
2860              "0x34bf3fc8 : 0x2a1976 (0x0 0x0 0x2a17ab 0x4023ef0)\n"
2861              "\n"
2862              "BSD process name corresponding to current thread: init\n"
2863              "\n"
2864              "Mac OS version:\n"
2865              "Not yet set\n"
2866              "\n"
2867              "Kernel version:\n"
2868              "Darwin Kernel version 10.8.0: Tue Jun  7 16:33:36 PDT 2011; "
2869              "root:xnu-1504.15-3~1/RELEASE_I386\n"
2870              "System model name: Macmini1,1 (Mac-F4208EC0)\n"
2871              "\n"
2872              "System uptime in nanoseconds: 13239332027\n"
2873              );
2874   BSOD_CURSOR (bst, CURSOR_BLOCK, 500000, 999999);
2875
2876   XClearWindow (dpy, window);
2877
2878   return bst;
2879 }
2880
2881
2882 /* 2017 MacOS 10.12 interminable software update, by jwz.
2883  */
2884 static struct bsod_state *
2885 macx_install (Display *dpy, Window window)
2886 {
2887   struct bsod_state *bst = make_bsod_state (dpy, window, "macinstall", "MacX");
2888
2889   int pix_w, pix_h;
2890   int x, y;
2891   int bw1, bh1;
2892   int bw2, bh2;
2893
2894   unsigned long fg = get_pixel_resource (dpy, bst->xgwa.colormap,
2895                                          "macinstall.foreground",
2896                                          "Mac.Foreground");
2897   unsigned long bg = get_pixel_resource (dpy, bst->xgwa.colormap,
2898                                          "macinstall.background",
2899                                          "Mac.Background");
2900   unsigned long fg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
2901                                          "macinstall.barForeground",
2902                                          "Mac.Foreground");
2903   unsigned long bg2 = get_pixel_resource (dpy, bst->xgwa.colormap,
2904                                          "macinstall.barBackground",
2905                                          "Mac.Background");
2906   char buf[1024];
2907   int lh = bst->font->ascent + bst->font->descent;
2908   int i, min;
2909   double pct;
2910
2911   Pixmap mask = 0;
2912   Pixmap pixmap = image_data_to_pixmap (dpy, window,
2913                                         apple_png, sizeof(apple_png),
2914                                         &pix_w, &pix_h, &mask);
2915
2916   bst->xoff = bst->left_margin = bst->right_margin = 0;
2917
2918   if (pixmap)
2919     {
2920       int i, n = 0;
2921       if (bst->xgwa.width > 2560) n++;  /* Retina displays */
2922       for (i = 0; i < n; i++)
2923         {
2924           pixmap = double_pixmap (dpy, bst->xgwa.visual, bst->xgwa.depth,
2925                                   pixmap, pix_w, pix_h);
2926           mask = double_pixmap (dpy, bst->xgwa.visual, 1, mask, pix_w, pix_h);
2927           pix_w *= 2;
2928           pix_h *= 2;
2929         }
2930     }
2931
2932   bst->pixmap = pixmap;
2933   bst->mask = mask;
2934
2935   x = (bst->xgwa.width - pix_w) / 2;
2936   y = (bst->xgwa.height) / 2  - pix_h;
2937   if (y < 0) y = 0;
2938
2939   XSetLineAttributes (dpy, bst->gc, 1, LineSolid, CapRound, JoinMiter);
2940
2941   BSOD_COLOR(bst, bg, bg);
2942   BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
2943   BSOD_COLOR(bst, fg, bg);
2944   BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, x, y);
2945   y += pix_h * 2 - lh;
2946
2947   /* progress bar */
2948   bw1 = pix_w * 2.5;
2949   bh1 = lh * 0.66;
2950   if (bh1 < 8) bh1 = 8;
2951
2952   x = (bst->xgwa.width - bw1) / 2;
2953   BSOD_COLOR(bst, fg2, bg);
2954   BSOD_LINE (bst, x,   y, x + bw1, y, bh1);
2955
2956   bw2 = bw1 - 1;
2957   bh2 = bh1 - 4;
2958   BSOD_COLOR(bst, bg2, bg);
2959   BSOD_LINE (bst, x+1, y, x + bw2, y, bh2);
2960
2961   BSOD_COLOR(bst, fg, bg);
2962   BSOD_LINE (bst, x,   y, x + 1, y, bh1);
2963
2964   pct = 5 + (random() % 40);
2965   min = 5 + (random() % 40);
2966
2967   for (i = 0; i < 100; i++) {
2968     pct += frand(0.3);
2969     min += (random() % 3) - 1;  /* sometimes down, mostly up */
2970
2971     if (pct > 90) pct = 90;
2972     BSOD_RECT (bst, True, x, y - bh1/2, bw1 * pct / 100, bh1);
2973
2974     sprintf (buf, "  Installing Software Update: about %d minutes.  ", min);
2975     bst->y = y + lh * 3;
2976     BSOD_TEXT (bst, CENTER, buf);
2977     BSOD_PAUSE (bst, 1000000);
2978   }
2979
2980   return bst;
2981 }
2982
2983
2984 static struct bsod_state *
2985 macx (Display *dpy, Window window)
2986 {
2987   switch (1?4:random() % 5) {
2988   case 0: return macx_10_0 (dpy, window);        break;
2989   case 1: return macx_10_2 (dpy, window, False); break;
2990   case 2: return macx_10_2 (dpy, window, True);  break;
2991   case 3: return mac_diskfail (dpy, window);     break;
2992   case 4: return macx_install (dpy, window);     break;
2993   default: abort();
2994   }
2995 }
2996
2997
2998 #ifndef HAVE_JWXYZ /* #### I have no idea how to implement this without
2999                            real plane-masks.  I don't think it would look
3000                            right if done with alpha-transparency... */
3001 /* blit damage
3002  *
3003  * by Martin Pool <mbp@samba.org>, Feb 2000.
3004  *
3005  * This is meant to look like the preferred failure mode of NCD
3006  * Xterms.  The parameters for choosing what to copy where might not
3007  * be quite right, but it looks about ugly enough.
3008  */
3009 static struct bsod_state *
3010 blitdamage (Display *dpy, Window window)
3011 {
3012   struct bsod_state *bst =
3013     make_bsod_state (dpy, window, "blitdamage", "BlitDamage");
3014
3015   int i;
3016   int delta_x = 0, delta_y = 0;
3017   int w, h;
3018   int chunk_h, chunk_w;
3019   int steps;
3020   int src_x, src_y;
3021   int x, y;
3022
3023   w = bst->xgwa.width;
3024   h = bst->xgwa.height;
3025
3026   XSetPlaneMask (dpy, bst->gc, random());
3027
3028   steps = 50;
3029   chunk_w = w / (random() % 1 + 1);
3030   chunk_h = h / (random() % 1 + 1);
3031   if (random() & 0x1000)
3032     delta_y = random() % 600;
3033   if (!delta_y || (random() & 0x2000))
3034     delta_x = random() % 600;
3035   src_x = 0;
3036   src_y = 0;
3037   x = 0;
3038   y = 0;
3039
3040   BSOD_IMG (bst);
3041   for (i = 0; i < steps; i++) {
3042     if (x + chunk_w > w)
3043       x -= w;
3044     else
3045       x += delta_x;
3046
3047     if (y + chunk_h > h)
3048       y -= h;
3049     else
3050       y += delta_y;
3051
3052     BSOD_COPY (bst, src_x, src_y, chunk_w, chunk_h, x, y);
3053     BSOD_PAUSE (bst, 1000);
3054   }
3055
3056   return bst;
3057 }
3058 #endif /* !HAVE_JWXYZ */
3059
3060
3061 /*
3062  * OS/2 panics, by Knut St. Osmundsen <bird-xscreensaver@anduin.net>
3063  *
3064  * All but one messages are real ones, some are from my test machines
3065  * and system dumps, others are reconstructed from google results.
3066  * Please, don't be to hard if the formatting of the earlier systems
3067  * aren't 100% correct.
3068  */
3069 static struct bsod_state *
3070 os2 (Display *dpy, Window window)
3071 {
3072   struct bsod_state *bst = make_bsod_state (dpy, window, "os2", "OS2");
3073
3074   __extension__
3075   static const char * const os2_panics[] =
3076     { /* OS/2 2.0 trap - details are bogus (CR0++). */
3077       "TRAP 0002       ERRCD=0000  ERACC=****  ERLIM=********\n"
3078       "EAX=7d240a58  EBX=ff202fdc  ECX=00064423  EDX=00003624\n"
3079       "ESI=fff3272c  EDI=7d240004  EBP=00004a44  FLG=00003202\n"
3080       "CS:EIP=0160:fff702a6  CSACC=c09d  CSLIM=ffffffff\n"
3081       "SS:ESP=0030:00004a38  SSACC=1097  SSLIM=00003fff\n"
3082       "DS=0158  DSACC=c0f3  DSLIM=ffffffff  CR0=fffffffb\n"
3083       "ES=0158  ESACC=c0f3  ESLIM=ffffffff  CR2=1a060014\n"
3084       "FS=0000  FSACC=****  FSLIM=********\n"
3085       "GS=0000  GSACC=****  GSLIM=********\n"
3086       "\n"
3087       "The system detected an internal processing error\n"
3088       "at location ##0160:fff6453f - 000d:a53f\n"
3089       "60000, 9084\n"
3090       "\n"
3091       "038600d1\n"
3092       "Internal revision 6.307, 92/03/01\n"
3093       "\n",
3094
3095       /* warp 3 (early) */
3096       "TRAP 000e       ERRCD=0000  ERACC=****  ERLIM=********\n"
3097       "EAX=ff050c20  EBX=000000bb  ECX=ffff00c1  EDx=fff379b8\n"
3098       "ESI=ffe55a3c  EDI=00000000  EBP=00004eb8  FLG=00013282\n"
3099       "CS:EIP=0160:fff8dbb8  CSACC=c09b  CSLIM=ffffffff\n"
3100       "SS:EIP=0030:00004eb4  SSACC=1097  SSLIM=00003fff\n"
3101       "DS=0158  DSACC=c0f3  DSLIM=ffffffff  CR0=8001001b\n"
3102       "ES=0158  DSACC=c0f3  DSLIM=ffffffff  CR2=000000c7\n"
3103       "FS=0000  FSACC=****  FSLIM=********\n"
3104       "GS=0000  GSACC=****  GSLIM=********\n"
3105       "\n"
3106       "The system detected an internal processing error\n"
3107       "at location ##0160:fff66bf0 - 000d:9bf0.\n"
3108       "60000, 9084\n"
3109       "\n"
3110       "048600b4\n"
3111       "Internal revision 8.125, 94/02/16\n"
3112       "\n"
3113       "The system is stopped.  Record the location number of the error\n"
3114       "and contact your service representative.\n",
3115
3116       /* warp 3 */
3117       "TRAP 000e       ERRCD=0002  ERACC=****  ERLIM=********\n"
3118       "EAX=00000000  EBX=fdef1e0c  ECX=00003824  EDX=0000edf9\n"
3119       "ESI=fdf30e80  EDI=fc8b0000  EBP=00005658  FLG=00012246\n"
3120       "CS:EIP=0160:fff8ada3  CSACC=c09b  CSLIM=ffffffff\n"
3121       "SS:ESP=0030:000055d4  SSACC=1097  SSLIM=0000480f\n"
3122       "DS=0158  DSACC=c093  DSLIM=ffffffff  CR0=8001001b\n"
3123       "ES=0158  ESACC=c093  ESLIM=ffffffff  CR2=fc8b0000\n"
3124       "FS=03b8  FSACC=0093  FSLIM=00000023\n"
3125       "GS=0000  GSACC=****  GSLIM=********\n"
3126       "\n"
3127       "The system detected an internal processing error\n"
3128       "at location ##0160:fff5c364 - 000d:a364.\n"
3129       "60000, 9084\n"
3130       "\n"
3131       "05860526\n"
3132       "Internal revision 8200,94/11/07\n"
3133       "\n"
3134       "The system is stopped. Record all of the above information and\n"
3135       "contact your service representative.\n",
3136
3137       /* warp 3 (late) */
3138       "TRAP 000d       ERRCD=2200  ERACC=1092  ERLIM=00010fff\n"
3139       "EAX=0000802e  EBX=fff001c8  ECX=9bd80000  EDX=00000000\n"
3140       "ESI=fff09bd8  EDI=fdeb001b  EBP=00000000  FLG=00012012\n"
3141       "CS:EIP=0168:fff480a2  CSACC=c09b  CSLIM=ffffffff\n"
3142       "SS:ESP=00e8:00001f32  SSACC=0093  SSLIM=00001fff\n"
3143       "DS=0940  DSACC=0093  DSLIM=00000397  CR0=8001001b\n"
3144       "ES=00e8  ESACC=0093  ESLIM=00001fff  CR2=15760008\n"
3145       "FS=0000  FSACC=****  FSLIM=****\n"
3146       "GS=0000  GSACC=****  GSLIM=****\n"
3147       "\n"
3148       "The system detected an internal processing error\n"
3149       "at location ##0168:fff4b06e - 000e:c06e\n"
3150       "60000, 9084\n"
3151       "\n"
3152       "06860652\n"
3153       "Internal revision 8.259_uni,98/01/07\n"
3154       "\n"
3155       "The system is stopped. Record all of the above information and\n"
3156       "contact your service representative.\n",
3157
3158       /* Warp 4.52+ - the official r0trap.exe from the debugging classes */
3159       "Exception in module: OS2KRNL\n"
3160       "TRAP 000e       ERRCD=0002  ERACC=****  ERLIM=********\n"
3161       "EAX=00000001  EBX=80010002  ECX=ffed4638  EDX=0003f17b\n"
3162       "ESI=00000001  EDI=00000002  EBP=00005408  FLG=00012202\n"
3163       "CS:EIP=0168:fff3cd2e  CSACC=c09b  CSLIM=ffffffff\n"
3164       "SS:ESP=0030:000053ec  SSACC=1097  SSLIM=000044ff\n"
3165       "DS=0160  DSACC=c093  DSLIM=ffffffff  CR0=8001001b\n"
3166       "ES=0160  ESACC=c093  ESLIM=ffffffff  CR2=00000001\n"
3167       "FS=0000  FSACC=****  FSLIM=********\n"
3168       "GS=0000  GSACC=****  GSLIM=********\n"
3169       "\n"
3170       "The system detected an internal processing error at\n"
3171       "location ##0168:fff1e3f3 - 000e:c3f3.\n"
3172       "60000, 9084\n"
3173       "\n"
3174       "068606a0\n"
3175       "Internal revision 14.097_UNI\n"
3176       "\n"
3177       "The system is stopped. Record all of the above information and\n"
3178       "contact your service representative.\n",
3179
3180       /* Warp 4.52+, typical JFS problem. */
3181       "Exeption in module: JFS\n"
3182       "TRAP 0003       ERRCD=0000  ERACC=****  ERLIM=********\n"
3183       "EAX=00000000  EBX=ffffff05  ECX=00000001  EDX=f5cd8010\n"
3184       "ESI=000000e6  EDI=000000e7  EBP=f9c7378e  FLG=00002296\n"
3185       "CS:EIP=0168:f8df3250  CSACC=c09b  CSLIM=ffffffff\n"
3186       "SS:ESP=1550:fdc73778  SSACC=c093  SSLIM=ffffffff\n"
3187       "DS=0160  DSACC=c093  DSLIM=ffffffff  CR0=80010016\n"
3188       "ES=0160  ESACC=c093  DSLIM=ffffffff  CR2=05318000\n"
3189       "FS=03c0  FSACC=0093  DSLIM=00000023\n"
3190       "GS=0160  GSACC=c093  DSLIM=ffffffff\n"
3191       "\n"
3192       "The system detected an internal processing error\n"
3193       "at location ##0168:fff1e2ab - 000e:c2ab.\n"
3194       "60000, 9084\n"
3195       "\n"
3196       "07860695\n"
3197       "\n"
3198       "Internal revision 14.100c_UNI\n"
3199       "\n"
3200       "The system is stopped. Record all of the above information and\n"
3201       "contact your service representative.\n"
3202     };
3203
3204   BSOD_TEXT (bst, LEFT, os2_panics[random() % countof(os2_panics)]);
3205   BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999);
3206
3207   XClearWindow (dpy, window);
3208   return bst;
3209 }
3210
3211
3212 /* SPARC Solaris panic. Should look pretty authentic on Solaris boxes.
3213  * Anton Solovyev <solovam@earthlink.net>
3214  */
3215 static struct bsod_state *
3216 sparc_solaris (Display *dpy, Window window)
3217 {
3218   struct bsod_state *bst = make_bsod_state (dpy, window, "solaris", "Solaris");
3219   int i;
3220
3221   bst->scroll_p = True;
3222   bst->wrap_p = True;
3223   bst->left_margin = bst->right_margin = bst->xgwa.width  * 0.07;
3224   bst->top_margin = bst->bottom_margin = bst->xgwa.height * 0.07;
3225   bst->y = bst->top_margin + bst->yoff + bst->font->ascent;
3226
3227   BSOD_IMG (bst);
3228   BSOD_PAUSE (bst, 3000000);
3229
3230   BSOD_INVERT(bst);
3231   BSOD_RECT (bst, True,
3232              bst->left_margin, bst->top_margin,
3233              bst->xgwa.width - bst->left_margin - bst->right_margin,
3234              bst->xgwa.height - bst->top_margin - bst->bottom_margin);
3235   BSOD_INVERT(bst);
3236
3237   BSOD_TEXT (bst, LEFT,
3238     "BAD TRAP: cpu=0 type=0x31 rp=0x2a10043b5e0 addr=0xf3880 mmu_fsr=0x0\n"
3239     "BAD TRAP occurred in module \"unix\" due to an illegal access to a"
3240     " user address.\n"
3241     "adb: trap type = 0x31\n"
3242     "addr=0xf3880\n"
3243     "pid=307, pc=0x100306e4, sp=0x2a10043ae81, tstate=0x4480001602,"
3244     " context=0x87f\n"
3245     "g1-g7: 1045b000, 32f, 10079440, 180, 300000ebde8, 0, 30000953a20\n"
3246     "Begin traceback... sp = 2a10043ae81\n"
3247     "Called from 100bd060, fp=2a10043af31, args=f3700 300008cc988 f3880 0"
3248     " 1 300000ebde0.\n"
3249     "Called from 101fe1bc, fp=2a10043b011, args=3000045a240 104465a0"
3250     " 300008e47d0 300008e48fa 300008ae350 300008ae410\n"
3251     "Called from 1007c520, fp=2a10043b0c1, args=300008e4878 300003596e8 0"
3252     " 3000045a320 0 3000045a220\n"
3253     "Called from 1007c498, fp=2a10043b171, args=1045a000 300007847f0 20"
3254     " 3000045a240 1 0\n"
3255     "Called from 1007972c, fp=2a10043b221, args=1 300009517c0 30000951e58 1"
3256     " 300007847f0 0\n"
3257     "Called from 10031e10, fp=2a10043b2d1, args=3000095b0c8 0 300009396a8"
3258     " 30000953a20 0 1\n"
3259     "Called from 10000bdd8, fp=ffffffff7ffff1c1, args=0 57 100131480"
3260     " 100131480 10012a6e0 0\n"
3261     "End traceback...\n"
3262     "panic[cpu0]/thread=30000953a20: trap\n"
3263     "syncing file systems...");
3264
3265   BSOD_PAUSE (bst, 3000000);
3266
3267   BSOD_TEXT (bst, LEFT, " 1 done\n");
3268   BSOD_TEXT (bst, LEFT, "dumping to /dev/dsk/c0t0d0s3, offset 26935296\n");
3269   BSOD_PAUSE (bst, 2000000);
3270
3271
3272   for (i = 1; i <= 100; ++i)
3273     {
3274       char buf[100];
3275       sprintf (buf, "\b\b\b\b\b\b\b\b\b\b\b%3d%% done", i);
3276       BSOD_TEXT (bst, LEFT, buf);
3277       BSOD_PAUSE (bst, 100000);
3278     }
3279
3280   BSOD_TEXT (bst, LEFT,
3281     ": 2803 pages dumped, compression ratio 2.88, dump succeeded\n");
3282   BSOD_PAUSE (bst, 2000000);
3283
3284   BSOD_TEXT (bst, LEFT,
3285     "rebooting...\n"
3286     "Resetting ...");
3287
3288   return bst;
3289 }
3290
3291
3292 /* Linux panic and fsck, by jwz
3293  */
3294 static struct bsod_state *
3295 linux_fsck (Display *dpy, Window window)
3296 {
3297   struct bsod_state *bst = make_bsod_state (dpy, window, "linux", "Linux");
3298
3299   int i;
3300   const char *sysname;
3301   char buf[1024];
3302 # ifdef HAVE_UNAME
3303   struct utsname uts;
3304 #endif /* UNAME */
3305
3306   const char *linux_panic[] = {
3307    " kernel: Unable to handle kernel paging request at virtual "
3308      "address 0000f0ad\n",
3309    " kernel:  printing eip:\n",
3310    " kernel: c01becd7\n",
3311    " kernel: *pde = 00000000\n",
3312    " kernel: Oops: 0000\n",
3313    " kernel: CPU:    0\n",
3314    " kernel: EIP:    0010:[<c01becd7>]    Tainted: P \n",
3315    " kernel: EFLAGS: 00010286\n",
3316    " kernel: eax: 0000ff00   ebx: ca6b7e00   ecx: ce1d7a60   edx: ce1d7a60\n",
3317    " kernel: esi: ca6b7ebc   edi: 00030000   ebp: d3655ca0   esp: ca6b7e5c\n",
3318    " kernel: ds: 0018   es: 0018   ss: 0018\n",
3319    " kernel: Process crond (pid: 1189, stackpage=ca6b7000)\n",
3320    " kernel: Stack: d3655ca0 ca6b7ebc 00030054 ca6b7e7c c01c1e5b "
3321        "00000287 00000020 c01c1fbf \n",
3322    "",
3323    " kernel:        00005a36 000000dc 000001f4 00000000 00000000 "
3324        "ce046d40 00000001 00000000 \n",
3325    "", "", "",
3326    " kernel:        ffffffff d3655ca0 d3655b80 00030054 c01bef93 "
3327        "d3655ca0 ca6b7ebc 00030054 \n",
3328    "", "", "",
3329    " kernel: Call Trace:    [<c01c1e5b>] [<c01c1fbf>] [<c01bef93>] "
3330        "[<c01bf02b>] [<c0134c4f>]\n",
3331    "", "", "",
3332    " kernel:   [<c0142562>] [<c0114f8c>] [<c0134de3>] [<c010891b>]\n",
3333    " kernel: \n",
3334    " kernel: Code: 2a 00 75 08 8b 44 24 2c 85 c0 74 0c 8b 44 24 58 83 48 18 "
3335       "08 \n",
3336    0
3337   };
3338
3339   bst->scroll_p = True;
3340   bst->wrap_p = True;
3341   bst->left_margin = bst->right_margin = 10;
3342   bst->top_margin = bst->bottom_margin = 10;
3343
3344   sysname = "linux";
3345 # ifdef HAVE_UNAME
3346   {
3347     char *s;
3348     if (uname (&uts) >= 0)
3349       sysname = uts.nodename;
3350     s = strchr (sysname, '.');
3351     if (s) *s = 0;
3352   }
3353 # endif /* !HAVE_UNAME */
3354
3355
3356   BSOD_TEXT (bst, LEFT, "waiting for X server to shut down ");
3357   BSOD_PAUSE (bst, 100000);
3358   BSOD_TEXT (bst, LEFT,
3359              "XIO:  fatal IO error 2 (broken pipe) on X server \":0.0\"\n"
3360              "        after 339471 requests (339471 known processed) "
3361              "with 0 events remaining\n");
3362   BSOD_CHAR_DELAY (bst, 300000);
3363   BSOD_TEXT (bst, LEFT, ".........\n");
3364   BSOD_CHAR_DELAY (bst, 0);
3365   BSOD_TEXT (bst, LEFT,
3366              "xinit:  X server slow to shut down, sending KILL signal.\n"
3367              "waiting for server to die ");
3368   BSOD_CHAR_DELAY (bst, 300000);
3369   BSOD_TEXT (bst, LEFT, "...\n");
3370   BSOD_CHAR_DELAY (bst, 0);
3371   BSOD_TEXT (bst, LEFT, "xinit:  Can't kill server\n");
3372   BSOD_PAUSE (bst, 2000000);
3373
3374   sprintf (buf, "\n%s Login: ", sysname);
3375   BSOD_TEXT (bst, LEFT, buf);
3376   BSOD_PAUSE (bst, 1000000);
3377   BSOD_TEXT (bst, LEFT,
3378     "\n\n"
3379     "Parallelizing fsck version 1.22 (22-Jun-2001)\n"
3380     "e2fsck 1.22, 22-Jun-2001 for EXT2 FS 0.5b, 95/08/09\n"
3381     "Warning!  /dev/hda1 is mounted.\n"
3382     "/dev/hda1 contains a file system with errors, check forced.\n");
3383   BSOD_PAUSE (bst, 1000000);
3384
3385   if (0 == random() % 2)
3386     BSOD_TEXT (bst, LEFT,
3387      "Couldn't find ext2 superblock, trying backup blocks...\n"
3388      "The filesystem size (according to the superblock) is 3644739 blocks\n"
3389      "The physical size of the device is 3636706 blocks\n"
3390      "Either the superblock or the partition table is likely to be corrupt!\n"
3391      "Abort<y>? no\n");
3392   BSOD_PAUSE (bst, 1000000);
3393
3394  AGAIN:
3395
3396   BSOD_TEXT (bst, LEFT, "Pass 1: Checking inodes, blocks, and sizes\n");
3397   BSOD_PAUSE (bst, 2000000);
3398
3399   i = (random() % 60) - 20;
3400   while (--i > 0)
3401     {
3402       int b = random() % 0xFFFF;
3403       sprintf (buf, "Deleted inode %d has zero dtime.  Fix<y>? yes\n\n", b);
3404       BSOD_TEXT (bst, LEFT, buf);
3405       BSOD_PAUSE (bst, 1000);
3406     }
3407
3408   i = (random() % 40) - 10;
3409   if (i > 0)
3410     {
3411       int g = random() % 0xFFFF;
3412       int b = random() % 0xFFFFFFF;
3413
3414       BSOD_PAUSE (bst, 1000000);
3415
3416       sprintf (buf, "Warning: Group %d's copy of the group descriptors "
3417                "has a bad block (%d).\n", g, b);
3418       BSOD_TEXT (bst, LEFT, buf);
3419
3420       b = random() % 0x3FFFFF;
3421       while (--i > 0)
3422         {
3423           b += random() % 0xFFFF;
3424           sprintf (buf,
3425                    "Error reading block %d (Attempt to read block "
3426                    "from filesystem resulted in short read) while doing "
3427                    "inode scan.  Ignore error<y>?",
3428                    b);
3429           BSOD_TEXT (bst, LEFT, buf);
3430           BSOD_PAUSE (bst, 10000);
3431           BSOD_TEXT (bst, LEFT, " yes\n\n");
3432         }
3433     }
3434
3435   if (0 == (random() % 10))
3436     {
3437       BSOD_PAUSE (bst, 1000000);
3438
3439       i = 3 + (random() % 10);
3440       while (--i > 0)
3441         {
3442           BSOD_TEXT (bst, LEFT,
3443                      "Could not allocate 256 block(s) for inode table: "
3444                      "No space left on device\n");
3445           BSOD_PAUSE (bst, 1000);
3446         }
3447       BSOD_TEXT (bst, LEFT, "Restarting e2fsck from the beginning...\n");
3448       BSOD_PAUSE (bst, 2000000);
3449
3450       goto AGAIN;
3451     }
3452
3453   i = (random() % 20) - 5;
3454
3455   if (i > 0)
3456     BSOD_PAUSE (bst, 1000000);
3457
3458   while (--i > 0)
3459     {
3460       int j = 5 + (random() % 10);
3461       int w = random() % 4;
3462
3463       while (--j > 0)
3464         {
3465           int b = random() % 0xFFFFF;
3466           int g = random() % 0xFFF;
3467
3468           if (0 == (random() % 10))
3469             b = 0;
3470           else if (0 == (random() % 10))
3471             b = -1;
3472
3473           if (w == 0)
3474             sprintf (buf,
3475                      "Inode table for group %d not in group.  (block %d)\n"
3476                      "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
3477                      "Relocate<y>?",
3478                      g, b);
3479           else if (w == 1)
3480             sprintf (buf,
3481                      "Block bitmap for group %d not in group.  (block %d)\n"
3482                      "Relocate<y>?",
3483                      g, b);
3484           else if (w == 2)
3485             sprintf (buf,
3486                      "Inode bitmap %d for group %d not in group.\n"
3487                      "Continue<y>?",
3488                      b, g);
3489           else /* if (w == 3) */
3490             sprintf (buf,
3491                      "Bad block %d in group %d's inode table.\n"
3492                      "WARNING: SEVERE DATA LOSS POSSIBLE.\n"
3493                      "Relocate<y>?",
3494                      b, g);
3495
3496           BSOD_TEXT (bst, LEFT, buf);
3497           BSOD_TEXT (bst, LEFT, " yes\n\n");
3498           BSOD_PAUSE (bst, 1000);
3499         }
3500     }
3501
3502
3503   if (0 == random() % 10) goto PANIC;
3504   BSOD_TEXT (bst, LEFT, "Pass 2: Checking directory structure\n");
3505   BSOD_PAUSE (bst, 2000000);
3506
3507   i = (random() % 20) - 5;
3508   while (--i > 0)
3509     {
3510       int n = random() % 0xFFFFF;
3511       int o = random() % 0xFFF;
3512       sprintf (buf, "Directory inode %d, block 0, offset %d: "
3513                "directory corrupted\n"
3514                "Salvage<y>? ",
3515                n, o);
3516       BSOD_TEXT (bst, LEFT, buf);
3517       BSOD_PAUSE (bst, 1000);
3518       BSOD_TEXT (bst, LEFT, " yes\n\n");
3519
3520       if (0 == (random() % 100))
3521         {
3522           sprintf (buf, "Missing '.' in directory inode %d.\nFix<y>?", n);
3523           BSOD_TEXT (bst, LEFT, buf);
3524           BSOD_PAUSE (bst, 1000);
3525           BSOD_TEXT (bst, LEFT, " yes\n\n");
3526         }
3527     }
3528
3529   if (0 == random() % 10)
3530     goto PANIC;
3531
3532   BSOD_TEXT (bst, LEFT,
3533              "Pass 3: Checking directory connectivity\n"
3534              "/lost+found not found.  Create? yes\n");
3535   BSOD_PAUSE (bst, 2000000);
3536
3537   /* Unconnected directory inode 4949 (/var/spool/squid/06/???)
3538      Connect to /lost+found<y>? yes
3539
3540      '..' in /var/spool/squid/06/08 (20351) is <The NULL inode> (0), should be
3541      /var/spool/squid/06 (20350).
3542      Fix<y>? yes
3543
3544      Unconnected directory inode 128337 (/var/spool/squid/06/???)
3545      Connect to /lost+found<y>? yes
3546    */
3547
3548
3549   if (0 == random() % 10) goto PANIC;
3550   BSOD_TEXT (bst, LEFT,  "Pass 4: Checking reference counts\n");
3551   BSOD_PAUSE (bst, 2000000);
3552
3553   /* Inode 2 ref count is 19, should be 20.  Fix<y>? yes
3554
3555      Inode 4949 ref count is 3, should be 2.  Fix<y>? yes
3556
3557         ...
3558
3559      Inode 128336 ref count is 3, should be 2.  Fix<y>? yes
3560
3561      Inode 128337 ref count is 3, should be 2.  Fix<y>? yes
3562
3563    */
3564
3565
3566   if (0 == random() % 10) goto PANIC;
3567   BSOD_TEXT (bst, LEFT,  "Pass 5: Checking group summary information\n");
3568   BSOD_PAUSE (bst, 2000000);
3569
3570   i = (random() % 200) - 50;
3571   if (i > 0)
3572     {
3573       BSOD_TEXT (bst, LEFT,  "Block bitmap differences: ");
3574       while (--i > 0)
3575         {
3576           sprintf (buf, " %d", -(random() % 0xFFF));
3577           BSOD_TEXT (bst, LEFT, buf);
3578           BSOD_PAUSE (bst, 1000);
3579         }
3580       BSOD_TEXT (bst, LEFT, "\nFix? yes\n\n");
3581     }
3582
3583
3584   i = (random() % 100) - 50;
3585   if (i > 0)
3586     {
3587       BSOD_TEXT (bst, LEFT,  "Inode bitmap differences: ");
3588       while (--i > 0)
3589         {
3590           sprintf (buf, " %d", -(random() % 0xFFF));
3591           BSOD_TEXT (bst, LEFT, buf);
3592           BSOD_PAUSE (bst, 1000);
3593         }
3594       BSOD_TEXT (bst, LEFT,  "\nFix? yes\n\n");
3595     }
3596
3597   i = (random() % 20) - 5;
3598   while (--i > 0)
3599     {
3600       int g = random() % 0xFFFF;
3601       int c = random() % 0xFFFF;
3602       sprintf (buf,
3603                "Free blocks count wrong for group #0 (%d, counted=%d).\nFix? ",
3604                g, c);
3605       BSOD_TEXT (bst, LEFT, buf);
3606       BSOD_PAUSE (bst, 1000);
3607       BSOD_TEXT (bst, LEFT,  " yes\n\n");
3608     }
3609
3610  PANIC:
3611
3612   i = 0;
3613   BSOD_TEXT (bst, LEFT,  "\n\n");
3614   while (linux_panic[i])
3615     {
3616       time_t t = time ((time_t *) 0);
3617       struct tm *tm = localtime (&t);
3618       char prefix[100];
3619
3620       if (*linux_panic[i])
3621         {
3622           strftime (prefix, sizeof(prefix)-1, "%b %d %H:%M:%S ", tm);
3623           BSOD_TEXT (bst, LEFT,  prefix);
3624           BSOD_TEXT (bst, LEFT,  sysname);
3625           BSOD_TEXT (bst, LEFT,  linux_panic[i]);
3626           BSOD_PAUSE (bst, 1000);
3627         }
3628       else
3629         BSOD_PAUSE (bst, 300000);
3630
3631       i++;
3632     }
3633   BSOD_PAUSE (bst, 4000000);
3634
3635   XClearWindow(dpy, window);
3636   return bst;
3637 }
3638
3639
3640 /*
3641  * Linux (hppa) panic, by Stuart Brady <sdbrady@ntlworld.com>
3642  * Output courtesy of M. Grabert
3643  */
3644 static struct bsod_state *
3645 hppa_linux (Display *dpy, Window window)
3646 {
3647   struct bsod_state *bst =
3648     make_bsod_state (dpy, window, "hppalinux", "HPPALinux");
3649
3650   int i = 0;
3651   const char *release, *sysname, *gccversion, *version;
3652   long int linedelay = 0;
3653   char ss[1024];
3654 # ifdef HAVE_UNAME
3655   struct utsname uts;
3656 # endif /* UNAME */
3657
3658   __extension__
3659   struct { long int delay; const char *string; } linux_panic[] =
3660     {{ 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"
3661           "\n\n\n\n\n\n\n\n\n\n\n\n\n" },
3662      { 0, "Linux version %s (root@%s) (gcc version %s) %s\n" },
3663      { 4000, "FP[0] enabled: Rev 1 Model 16\n" },
3664      { 10, "The 32-bit Kernel has started...\n" },
3665      { -1, "Determining PDC firmware type: System Map.\n" },
3666      { -1, "model 00005bb0 00000481 00000000 00000002 7778df9f 100000f0 "
3667            "00000008 000000b2 000000b2\n" },
3668      { -1, "vers  00000203\n" },
3669      { -1, "CPUID vers 17 rev 7 (0x00000227)\n" },
3670      { -1, "capabilities 0x3\n" },
3671      { -1, "model 9000/785/C3000\n" },
3672      { -1, "Total Memory: 1024 Mb\n" },
3673      { -1, "On node 0 totalpages: 262144\n" },
3674      { -1, "  DMA zone: 262144 pages, LIFO batch:16\n" },
3675      { -1, "  Normal zone: 0 pages, LIFO batch:1\n" },
3676      { -1, "  HighMem zone: 0 pages, LIFO batch:1\n" },
3677      { -1, "LCD display at f05d0008,f05d0000 registered\n" },
3678      { -1, "Building zonelist for node : 0\n" },
3679      { -1, "Kernel command line: ide=nodma root=/dev/sda3 HOME=/ ip=off "
3680            "console=ttyS0 TERM=vt102 palo_kernel=2/vmlinux-2.6\n" },
3681      { -1, "ide_setup: ide=nodmaIDE: Prevented DMA\n" },
3682      { -1, "PID hash table entries: 16 (order 4: 128 bytes)\n" },
3683      {500, "Console: colour dummy device 160x64\n" },
3684      { 10, "Memory: 1034036k available\n" },
3685      { -1, "Calibrating delay loop... 796.67 BogoMIPS\n" },
3686      { -1, "Dentry cache hash table entries: 131072 (order: 7, 524288 "
3687            "bytes)\n" },
3688      { -1, "Inode-cache hash table entries: 65536 (order: 6, 262144 "
3689            "bytes)\n" },
3690      { -1, "Mount-cache hash table entries: 512 (order: 0, 4096 bytes)\n" },
3691      { -1, "POSIX conformance testing by UNIFIX\n" },
3692      { -1, "NET: Registered protocol family 16\n" },
3693      { 100, "Searching for devices...\n" },
3694      { 25, "Found devices:\n" },
3695      { 10, "1. Astro BC Runway Port at 0xfed00000 [10] "
3696            "{ 12, 0x0, 0x582, 0x0000b }\n" },
3697      { -1, "2. Elroy PCI Bridge at 0xfed30000 [10/0] "
3698            "{ 13, 0x0, 0x782, 0x0000a }\n" },
3699      { -1, "3. Elroy PCI Bridge at 0xfed32000 [10/1] "
3700            "{ 13, 0x0, 0x782, 0x0000a }\n" },
3701      { -1, "4. Elroy PCI Bridge at 0xfed38000 [10/4] "
3702            "{ 13, 0x0, 0x782, 0x0000a }\n" },
3703      { -1, "5. Elroy PCI Bridge at 0xfed3c000 [10/6] "
3704            "{ 13, 0x0, 0x782, 0x0000a }\n" },
3705      { -1, "6. AllegroHigh W at 0xfffa0000 [32] "
3706            "{ 0, 0x0, 0x5bb, 0x00004 }\n" },
3707      { -1, "7. Memory at 0xfed10200 [49] { 1, 0x0, 0x086, 0x00009 }\n" },
3708      { -1, "CPU(s): 1 x PA8500 (PCX-W) at 400.000000 MHz\n" },
3709      { -1, "SBA found Astro 2.1 at 0xfed00000\n" },
3710      { -1, "lba version TR2.1 (0x2) found at 0xfed30000\n" },
3711      { -1, "lba version TR2.1 (0x2) found at 0xfed32000\n" },
3712      { -1, "lba version TR2.1 (0x2) found at 0xfed38000\n" },
3713      { -1, "lba version TR2.1 (0x2) found at 0xfed3c000\n" },
3714      { 100, "SCSI subsystem initialized\n" },
3715      { 10, "drivers/usb/core/usb.c: registered new driver usbfs\n" },
3716      { -1, "drivers/usb/core/usb.c: registered new driver hub\n" },
3717      { -1, "ikconfig 0.7 with /proc/config*\n" },
3718      { -1, "Initializing Cryptographic API\n" },
3719      { 250, "SuperIO: probe of 0000:00:0e.0 failed with error -1\n" },
3720      { 20, "SuperIO: Found NS87560 Legacy I/O device at 0000:00:0e.1 "
3721            "(IRQ 64)\n" },
3722      { -1, "SuperIO: Serial port 1 at 0x3f8\n" },
3723      { -1, "SuperIO: Serial port 2 at 0x2f8\n" },
3724      { -1, "SuperIO: Parallel port at 0x378\n" },
3725      { -1, "SuperIO: Floppy controller at 0x3f0\n" },
3726      { -1, "SuperIO: ACPI at 0x7e0\n" },
3727      { -1, "SuperIO: USB regulator enabled\n" },
3728      { -1, "SuperIO: probe of 0000:00:0e.2 failed with error -1\n" },
3729      { -1, "Soft power switch enabled, polling @ 0xf0400804.\n" },
3730      { -1, "pty: 256 Unix98 ptys configured\n" },
3731      { -1, "Generic RTC Driver v1.07\n" },
3732      { -1, "Serial: 8250/16550 driver $" "Revision: 1.100 $ 13 ports, "
3733            "IRQ sharing disabled\n" },
3734      { -1, "ttyS0 at I/O 0x3f8 (irq = 0) is a 16550A\n" },
3735      { -1, "ttyS1 at I/O 0x2f8 (irq = 0) is a 16550A\n" },
3736      { -1, "Linux Tulip driver version 1.1.13 (May 11, 2002)\n" },
3737      { 150, "tulip0: no phy info, aborting mtable build\n" },
3738      { 10, "tulip0:  MII transceiver #1 config 1000 status 782d "
3739            "advertising 01e1.\n" },
3740      { -1, "eth0: Digital DS21143 Tulip rev 65 at 0xf4008000, "
3741            "00:10:83:F9:B4:34, IRQ 66.\n" },
3742      { -1, "Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2\n" },
3743      { -1, "ide: Assuming 33MHz system bus speed for PIO modes; "
3744            "override with idebus=xx\n" },
3745      { 100, "SiI680: IDE controller at PCI slot 0000:01:06.0\n" },
3746      { 10, "SiI680: chipset revision 2\n" },
3747      { -1, "SiI680: BASE CLOCK == 133\n" },
3748      { -1, "SiI680: 100% native mode on irq 128\n" },
3749      { -1, "    ide0: MMIO-DMA at 0xf4800000-0xf4800007 -- "
3750            "Error, MMIO ports already in use.\n" },
3751      { -1, "    ide1: MMIO-DMA at 0xf4800008-0xf480000f -- "
3752            "Error, MMIO ports already in use.\n" },
3753      { 5, "hda: TS130220A2, ATA DISK drive\n" },
3754      { -1, "      _______________________________\n" },
3755      { -1, "     < Your System ate a SPARC! Gah! >\n" },
3756      { -1, "      -------------------------------\n" },
3757      { -1, "             \\   ^__^\n" },
3758      { -1, "              \\  (xx)\\_______\n" },
3759      { -1, "                 (__)\\       )\\/\\\n" },
3760      { -1, "                  U  ||----w |\n" },
3761      { -1, "                     ||     ||\n" },
3762      { -1, "swapper (pid 1): Breakpoint (code 0)\n" },
3763      { -1, "\n" },
3764      { -1, "     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n" },
3765      { -1, "PSW: 00000000000001001111111100001111 Not tainted\n" },
3766      { -1, "r00-03  4d6f6f21 1032f010 10208f34 103fc2e0\n" },
3767      { -1, "r04-07  103fc230 00000001 00000001 0000000f\n" },
3768      { -1, "r08-11  103454f8 000f41fa 372d3980 103ee404\n" },
3769      { -1, "r12-15  3ccbf700 10344810 103ee010 f0400004\n" },
3770      { -1, "r16-19  f00008c4 f000017c f0000174 00000000\n" },
3771      { -1, "r20-23  fed32840 fed32800 00000000 0000000a\n" },
3772      { -1, "r24-27  0000ffa0 000000ff 103fc2e0 10326010\n" },
3773      { -1, "r28-31  00000000 00061a80 4ff98340 10208f34\n" },
3774      { -1, "sr0-3   00000000 00000000 00000000 00000000\n" },
3775      { -1, "sr4-7   00000000 00000000 00000000 00000000\n" },
3776      { -1, "\n" },
3777      { -1, "IASQ: 00000000 00000000 IAOQ: 00000000 00000004\n" },
3778      { -1, " IIR: 00000000    ISR: 00000000  IOR: 00000000\n" },
3779      { -1, " CPU:        0   CR30: 4ff98000 CR31: 1037c000\n" },
3780      { -1, " ORIG_R28: 55555555\n" },
3781      { -1, " IAOQ[0]: 0x0\n" },
3782      { -1, " IAOQ[1]: 0x4\n" },
3783      { -1, " RP(r2): probe_hwif+0x218/0x44c\n" },
3784      { -1, "Kernel panic: Attempted to kill init!\n" },
3785      { 0, NULL }};
3786
3787   bst->scroll_p = True;
3788   bst->wrap_p = True;
3789   bst->left_margin = bst->right_margin = 10;
3790   bst->top_margin = bst->bottom_margin = 10;
3791
3792   release = "2.6.0-test11-pa2";
3793   sysname = "hppa";
3794   version = "#2 Mon Dec 8 06:09:27 GMT 2003";
3795 # ifdef HAVE_UNAME
3796   {
3797     char *s;
3798     if (uname (&uts) >= 0)
3799       {
3800         sysname = uts.nodename;
3801         if (!strcmp (uts.sysname, "Linux"))
3802           {
3803             release = uts.release;
3804             version = uts.version;
3805           }
3806       }
3807     s = strchr (sysname, '.');
3808     if (s) *s = 0;
3809   }
3810 # endif /* !HAVE_UNAME */
3811
3812 # if (defined (__GNUC__) && defined (__VERSION__))
3813   gccversion = __VERSION__;
3814 # else /* !(defined (__GNUC__) && defined (__VERSION__)) */
3815   gccversion = "3.3.2 (Debian)";
3816 # endif /* !(defined (__GNUC__) && defined (__VERSION__)) */
3817
3818   /* Insert current host name into banner on line 2 */
3819   {
3820     snprintf (ss, 1024, linux_panic[1].string,
3821               release, sysname, gccversion, version);
3822     linux_panic[1].string = ss;
3823   }
3824
3825   BSOD_PAUSE (bst, 100000);
3826   while (linux_panic[i].string)
3827     {
3828       if (linux_panic[i].delay != -1)
3829         linedelay = linux_panic[i].delay * 1000;
3830       BSOD_PAUSE (bst, linedelay);
3831       BSOD_TEXT (bst, LEFT, linux_panic[i].string);
3832       i++;
3833     }
3834
3835   bst->y = bst->xgwa.height - bst->yoff
3836     - bst->font->ascent - bst->font->descent;
3837
3838   XClearWindow(dpy, window);
3839   return bst;
3840 }
3841
3842
3843 /* VMS by jwz (text sent by Roland Barmettler <roli@barmettler.net>)
3844  */
3845 static struct bsod_state *
3846 vms (Display *dpy, Window window)
3847 {
3848   struct bsod_state *bst = make_bsod_state (dpy, window, "vms", "VMS");
3849
3850   const char *sysname;
3851   int char_delay = 0;
3852   int dot_delay = 40000;
3853   int chunk_delay = 500000;
3854   char *s, *s1;
3855   int i;
3856   int arg_count;
3857 # ifdef HAVE_UNAME
3858   struct utsname uts;
3859 # endif /* UNAME */
3860
3861   __extension__
3862
3863   const char *lines[] = {
3864     "%CNXMAN,  Lost connection to system #\n"
3865     "%SHADOW-I-VOLPROC, DSA0: shadow master has changed.  "
3866     "Dump file WILL be written if system crashes.\n"
3867     "\n",
3868     "",
3869
3870     "%CNXMAN,  Quorum lost, blocking activity\n"
3871     "%CNXMAN,  Timed-out lost connection to system #\n"
3872     "%CNXMAN,  Timed-out lost connection to system #\n"
3873     "%CNXMAN,  Timed-out lost connection to system #\n"
3874     "%CNXMAN,  Proposing reconfiguration of the VMScluster\n",
3875     "",
3876
3877     "%CNXMAN,  Removed from VMScluster system #\n"
3878     "%CNXMAN,  Removed from VMScluster system #\n"
3879     "%CNXMAN,  Removed from VMScluster system #\n"
3880     "%CNXMAN,  Completing VMScluster state transition\n",
3881
3882     "\n"
3883     "**** OpenVMS (TM) Alpha Operating system V7.3-1   - BUGCHECK ****\n"
3884     "\n"
3885     "** Bugcheck code = 000005DC: CLUEXIT, Node voluntarily exiting "
3886     "VMScluster\n"
3887     "** Crash CPU: 00    Primary CPU: 00    Active CPUs: 00000001\n"
3888     "** Current Process = NULL\n"
3889     "** Current PSB ID = 00000001\n"
3890     "** Image Name =\n"
3891     "\n"
3892     "** Dumping error log buffers to HBVS unit 0\n"
3893     "**** Unable to dump error log buffers to remaining shadow set members\n"
3894     "** Error log buffers not dumped to HBVS unit 200\n"
3895     "\n"
3896     "** Dumping memory to HBVS unit 0\n"
3897     "**** Starting compressed selective memory dump at #...\n",
3898
3899     "...",
3900
3901     "\n"
3902     "**** Memory dump complete - not all processes or global pages saved\n",
3903
3904     "\n"
3905     "halted CPU 0\n",
3906     "",
3907
3908     "\n"
3909     "halt code = 5\n"
3910     "HALT instruction executed\n"
3911     "PC = ffffffff800c3884\n",
3912
3913     "\n"
3914     "CPU 0 booting\n",
3915
3916     "\n"
3917     "resetting all I/O buses\n"
3918     "\n"
3919     "\n"
3920     };
3921   char *args[8];
3922   int ids[3];
3923
3924   bst->scroll_p = True;
3925   bst->wrap_p = True;
3926   bst->left_margin = bst->right_margin = 10;
3927   bst->top_margin = bst->bottom_margin = 10;
3928
3929   sysname = "VMS001";
3930 # ifdef HAVE_UNAME
3931   {
3932     if (uname (&uts) >= 0)
3933       sysname = uts.nodename;
3934     s = strchr (sysname, '.');
3935     if (s) *s = 0;
3936   }
3937 # endif /* !HAVE_UNAME */
3938
3939   args[0] = malloc (strlen(sysname) + 7);
3940   strcpy (args[0], sysname);
3941   args[0][5] = 0;
3942
3943   /* Pick three numbers, 1-9, no overlaps. */
3944   ids[0] = 1 + (random() % 9);
3945   do { ids[1] = 1 + (random() % 9); } while (ids[1]==ids[0]);
3946   do { ids[2] = 1 + (random() % 9); } while (ids[2]==ids[0] || ids[2]==ids[1]);
3947
3948   i = strlen(args[0])-1;
3949   if (i < 6) i++;
3950   args[0][i] = '0' + ids[0];
3951   args[0][i+1] = 0;
3952
3953   for (s = args[0]; *s; s++)
3954     if (isalpha(*s)) *s = toupper (*s);
3955
3956   args[1] = strdup (args[0]);
3957   args[2] = strdup (args[0]); args[2][i] = '0' + ids[1];
3958   args[3] = strdup (args[0]); args[3][i] = '0' + ids[2];
3959
3960   args[4] = strdup (args[1]);
3961   args[5] = strdup (args[2]);
3962   args[6] = strdup (args[3]);
3963
3964   {
3965     time_t t = time ((time_t *) 0);
3966     struct tm *tm = localtime (&t);
3967     args[7] = malloc (30);
3968     strftime (args[7], 29, "%d-%b-%Y %H:%M", tm);
3969     for (s = args[7]; *s; s++)
3970       if (isalpha(*s)) *s = toupper (*s);
3971   }
3972
3973   arg_count = 0;
3974   for (i = 0; i < countof(lines); i++)
3975     {
3976       const char *fmt = lines[i];
3977       if (! strcmp (fmt, "..."))
3978         {
3979           int steps = 180 + (random() % 60);
3980           while (--steps >= 0)
3981             {
3982               BSOD_TEXT (bst, LEFT, ".");
3983               BSOD_PAUSE (bst, dot_delay);
3984             }
3985         }
3986       else
3987         {
3988           char *fmt2 = malloc (strlen (fmt) * 2 + 1);
3989           for (s = (char *) fmt, s1 = fmt2; *s; s++)
3990             {
3991               if (*s == '#')
3992                 {
3993                   strcpy (s1, args[arg_count++]);
3994                   s1 += strlen(s1);
3995                 }
3996               else
3997                 *s1++ = *s;
3998             }
3999           *s1 = 0;
4000           BSOD_CHAR_DELAY (bst, char_delay);
4001           BSOD_TEXT (bst, LEFT, fmt2);
4002           free (fmt2);
4003           BSOD_CHAR_DELAY (bst, 0);
4004           BSOD_PAUSE (bst, chunk_delay);
4005         }
4006     }
4007
4008   for (i = 0; i < countof (args); i++)
4009     free (args[i]);
4010
4011   XClearWindow(dpy, window);
4012   return bst;
4013 }
4014
4015
4016 /* HVX (formerly GCOS6) and TPS6 crash
4017    by Brian Garratt <brian-m.garratt@bull.co.uk>
4018
4019    GCOS6 is a Unix-like operating system developed by Honeywell in the
4020    1970s in collaboration with MIT and AT&T (who called their version
4021    UNIX).  Both are very much like MULTICS which Honeywell got from GE.
4022
4023    HVX ("High-performance Virtual System on Unix") is an AIX application
4024    which emulates GCOS6 hardware on RS6000-like machines.
4025  */
4026 static struct bsod_state *
4027 hvx (Display *dpy, Window window)
4028 {
4029   struct bsod_state *bst = make_bsod_state (dpy, window, "hvx", "HVX");
4030
4031   bst->scroll_p = True;
4032   bst->wrap_p = True;
4033   bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
4034     - bst->font->ascent;
4035
4036   BSOD_CHAR_DELAY (bst, 10000);
4037   BSOD_TEXT (bst, LEFT,
4038      "(TP) Trap no E   Effective address 00000000   Instruction D7DE\n"
4039      "(TP)  Registers :\n"
4040      "(TP)  B1 -> B7  03801B02  00000000  03880D45  038BABDB  0388AFFD"
4041      "  0389B3F8  03972317\n"
4042      "(TP)  R1 -> R7  0001  0007  F10F  090F  0020  0106  0272\n"
4043      "(TP)  P I Z M1  0388A18B  3232  0000 FF00\n"
4044      "(TP) Program counter is at offset 0028 from string YTPAD\n"
4045      "(TP) User id of task which trapped is LT 626\n"
4046      "(TP)?\n"
4047      );
4048   BSOD_PAUSE (bst, 1000000);
4049
4050   BSOD_CHAR_DELAY (bst, 100000);
4051   BSOD_TEXT (bst, LEFT, " TP CLOSE ALL");
4052
4053   BSOD_CHAR_DELAY (bst, 10000);
4054   BSOD_TEXT (bst, LEFT, "\n(TP)?\n");
4055   BSOD_PAUSE (bst, 1000000);
4056
4057   BSOD_CHAR_DELAY (bst, 100000);
4058   BSOD_TEXT (bst, LEFT, " TP ABORT -LT ALL");
4059
4060   BSOD_CHAR_DELAY (bst, 10000);
4061   BSOD_TEXT (bst, LEFT, "\n(TP)?\n");
4062   BSOD_PAUSE (bst, 1000000);
4063
4064   BSOD_CHAR_DELAY (bst, 100000);
4065   BSOD_TEXT (bst, LEFT, "  TP STOP KILL");
4066
4067   BSOD_CHAR_DELAY (bst, 10000);
4068   BSOD_TEXT (bst, LEFT,
4069      "\n"
4070      "(TP)?\n"
4071      "Core dumps initiated for selected HVX processes ...\n"
4072      "Core dumps complete.\n"
4073      "Fri Jul 19 15:53:09 2002\n"
4074      "Live registers for cp 0:\n"
4075      " P    =     7de3  IW=0000     I=32    CI=30000000   S=80006013"
4076      "   IV=aa0      Level=13\n"
4077      " R1-7 =       1f      913       13        4        8        0        0\n"
4078      " B1-7 =   64e71b      a93      50e   64e73c     6c2c     7000      b54\n"
4079      "Memory dump starting to file /var/hvx/dp01/diag/Level2 ...\n"
4080      "Memory dump complete.\n"
4081     );
4082
4083   XClearWindow(dpy, window);
4084   return bst;
4085 }
4086
4087
4088 /* HPUX panic, by Tobias Klausmann <klausman@schwarzvogel.de>
4089  */
4090 static struct bsod_state *
4091 hpux (Display *dpy, Window window)
4092 {
4093   struct bsod_state *bst = make_bsod_state (dpy, window, "hpux", "HPUX");
4094   const char *sysname;
4095   char buf[2048];
4096 # ifdef HAVE_UNAME
4097   struct utsname uts;
4098 # endif /* UNAME */
4099
4100   bst->scroll_p = True;
4101   bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
4102     - bst->font->ascent;
4103
4104   sysname = "HPUX";
4105 # ifdef HAVE_UNAME
4106   {
4107     char *s;
4108     if (uname (&uts) >= 0)
4109       sysname = uts.nodename;
4110     s = strchr (sysname, '.');
4111     if (s) *s = 0;
4112   }
4113 # endif /* !HAVE_UNAME */
4114
4115   BSOD_TEXT (bst, LEFT,
4116              "                                                       "
4117              "                                                       "
4118              "                                                       \n");
4119   sprintf (buf, "%.100s [HP Release B.11.00] (see /etc/issue)\n", sysname);
4120   BSOD_TEXT (bst, LEFT, buf);
4121   BSOD_PAUSE (bst, 1000000);
4122   BSOD_TEXT (bst, LEFT,
4123    "Console Login:\n"
4124    "\n"
4125    "     ******* Unexpected HPMC/TOC. Processor HPA FFFFFFFF'"
4126    "FFFA0000 *******\n"
4127    "                              GENERAL REGISTERS:\n"
4128    "r00/03 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
4129    "006C76C0\n"
4130    "r04/07 00000000'00000001 00000000'0126E328 00000000'00000000 00000000'"
4131    "0122B640\n"
4132    "r08/11 00000000'00000000 00000000'0198CFC0 00000000'000476FE 00000000'"
4133    "00000001\n"
4134    "r12/15 00000000'40013EE8 00000000'08000080 00000000'4002530C 00000000'"
4135    "4002530C\n"
4136    "r16/19 00000000'7F7F2A00 00000000'00000001 00000000'00000000 00000000'"
4137    "00000000\n"
4138    "r20/23 00000000'006C8048 00000000'00000001 00000000'00000000 00000000'"
4139    "00000000\n"
4140    "r24/27 00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
4141    "00744378\n"
4142    "r28/31 00000000'00000000 00000000'007DD628 00000000'0199F2B0 00000000'"
4143    "00000000\n"
4144    "                              CONTROL REGISTERS:\n"
4145    "sr0/3  00000000'0F3B4000 00000000'0C2A2000 00000000'016FF800 00000000'"
4146    "00000000\n"
4147    "sr4/7  00000000'00000000 00000000'016FF800 00000000'0DBF1400 00000000'"
4148    "00000000\n"
4149    "pcq =  00000000'00000000.00000000'00104950 00000000'00000000.00000000'"
4150    "00104A14\n"
4151    "isr =  00000000'10240006 ior = 00000000'67D9E220 iir = 08000240 rctr = "
4152    "7FF10BB6\n"
4153    "\n"
4154    "pid reg cr8/cr9    00007700'0000B3A9 00000000'0000C5D8\n"
4155    "pid reg cr12/cr13  00000000'00000000 00000000'00000000\n"
4156    "ipsw = 000000FF'080CFF1F iva = 00000000'0002C000 sar = 3A ccr = C0\n"
4157    "tr0/3  00000000'006C76C0 00000000'00000001 00000000'00000000 00000000'"
4158    "7F7CE000\n"
4159    "tr4/7  00000000'03790000 0000000C'4FB68340 00000000'C07EE13F 00000000'"
4160    "0199F2B0\n"
4161    "eiem = FFFFFFF0'FFFFFFFF eirr = 80000000'00000000 itmr = 0000000C'"
4162    "4FD8EDE1\n"
4163    "cr1/4  00000000'00000000 00000000'00000000 00000000'00000000 00000000'"
4164    "00000000\n"
4165    "cr5/7  00000000'00000000 00000000'00000000 00000000'"
4166    "00000000\n"
4167    "                           MACHINE CHECK PARAMETERS:\n"
4168    "Check Type = 00000000 CPU STATE = 9E000001 Cache Check = 00000000\n"
4169    "TLB Check = 00000000 Bus Check = 00000000 PIM State = ? SIU "
4170    "Status = ????????\n"
4171    "Assists = 00000000 Processor = 00000000\n"
4172    "Slave Addr = 00000000'00000000 Master Addr = 00000000'00000000\n"
4173    "\n"
4174    "\n"
4175    "TOC,    pcsq.pcoq = 0'0.0'104950   , isr.ior = 0'10240006.0'67d9e220\n"
4176    "@(#)B2352B/9245XB HP-UX (B.11.00) #1: Wed Nov  5 22:38:19 PST 1997\n"
4177    "Transfer of control: (display==0xd904, flags==0x0)\n"
4178    "\n"
4179    "\n"
4180    "\n"
4181    "*** A system crash has occurred.  (See the above messages for details.)\n"
4182    "*** The system is now preparing to dump physical memory to disk, for use\n"
4183    "*** in debugging the crash.\n"
4184    "\n"
4185    "*** The dump will be a SELECTIVE dump:  40 of 256 megabytes.\n"
4186    "*** To change this dump type, press any key within 10 seconds.\n"
4187    "*** Proceeding with selective dump.\n"
4188    "\n"
4189    "*** The dump may be aborted at any time by pressing ESC.\n");
4190
4191   {
4192     int i;
4193     int steps = 11;
4194     int size = 40;
4195     for (i = 0; i <= steps; i++)
4196       {
4197         if (i > steps) i = steps;
4198         sprintf (buf,
4199                "*** Dumping: %3d%% complete (%d of 40 MB) (device 64:0x2)\r",
4200                  i * 100 / steps,
4201                  i * size / steps);
4202         BSOD_TEXT (bst, LEFT, buf);
4203         BSOD_PAUSE (bst, 1500000);
4204       }
4205   }
4206
4207   BSOD_TEXT (bst, LEFT, "\n*** System rebooting.\n");
4208
4209   XClearWindow(dpy, window);
4210   return bst;
4211 }
4212
4213
4214 /* IBM OS/390 aka MVS aka z/OS.
4215    Text from Dan Espen <dane@mk.telcordia.com>.
4216    Apparently this isn't actually a crash, just a random session...
4217    But who can tell.
4218  */
4219 static struct bsod_state *
4220 os390 (Display *dpy, Window window)
4221 {
4222   struct bsod_state *bst = make_bsod_state (dpy, window, "os390", "OS390");
4223
4224   bst->scroll_p = True;
4225   bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
4226     - bst->font->ascent;
4227
4228   BSOD_LINE_DELAY (bst, 100000);
4229   BSOD_TEXT (bst, LEFT,
4230    "\n*** System rebooting.\n"
4231    "* ISPF Subtask abend *\n"
4232    "SPF      ENDED DUE TO ERROR+\n"
4233    "READY\n"
4234    "\n"
4235    "IEA995I SYMPTOM DUMP OUTPUT\n"
4236    "  USER COMPLETION CODE=0222\n"
4237    " TIME=23.00.51  SEQ=03210  CPU=0000  ASID=00AE\n"
4238    " PSW AT TIME OF ERROR  078D1000   859DAF18  ILC 2  INTC 0D\n"
4239    "   NO ACTIVE MODULE FOUND\n"
4240    "   NAME=UNKNOWN\n"
4241    "   DATA AT PSW  059DAF12 - 00181610  0A0D9180  70644710\n"
4242    "   AR/GR 0: 00000000/80000000   1: 00000000/800000DE\n"
4243    "         2: 00000000/196504DC   3: 00000000/00037A78\n"
4244    "         4: 00000000/00037B78   5: 00000000/0003351C\n"
4245    "         6: 00000000/0000F0AD   7: 00000000/00012000\n"
4246    "         8: 00000000/059DAF10   9: 00000000/0002D098\n"
4247    "         A: 00000000/059D9F10   B: 00000000/059D8F10\n"
4248    "         C: 00000000/859D7F10   D: 00000000/00032D60\n"
4249    "         E: 00000000/00033005   F: 01000002/00000041\n"
4250    " END OF SYMPTOM DUMP\n"
4251    "ISPS014 - ** Logical screen request failed - abend 0000DE **\n"
4252    "ISPS015 - ** Contact your system programmer or dialog developer.**\n"
4253    "*** ISPF Main task abend ***\n"
4254    "IEA995I SYMPTOM DUMP OUTPUT\n"
4255    "  USER COMPLETION CODE=0222\n"
4256    " TIME=23.00.52  SEQ=03211  CPU=0000  ASID=00AE\n"
4257    " PSW AT TIME OF ERROR  078D1000   8585713C  ILC 2  INTC 0D\n"
4258    "   ACTIVE LOAD MODULE           ADDRESS=05855000  OFFSET=0000213C\n"
4259    "   NAME=ISPMAIN\n"
4260    "   DATA AT PSW  05857136 - 00181610  0A0D9180  D3304770\n"
4261    "   GR 0: 80000000   1: 800000DE\n"
4262    "      2: 00015260   3: 00000038\n"
4263    "      4: 00012508   5: 00000000\n"
4264    "      6: 000173AC   7: FFFFFFF8\n"
4265    "      8: 05858000   9: 00012CA0\n"
4266    "      A: 05857000   B: 05856000\n"
4267    "      C: 85855000   D: 00017020\n"
4268    "      E: 85857104   F: 00000000\n"
4269    " END OF SYMPTOM DUMP\n"
4270    "READY\n"
4271    "***");
4272   BSOD_CURSOR (bst, CURSOR_LINE, 240000, 999999);
4273
4274   XClearWindow(dpy, window);
4275   return bst;
4276 }
4277
4278
4279 /* Compaq Tru64 Unix panic, by jwz as described by
4280    Tobias Klausmann <klausman@schwarzvogel.de>
4281  */
4282 static struct bsod_state *
4283 tru64 (Display *dpy, Window window)
4284 {
4285   struct bsod_state *bst = make_bsod_state (dpy, window, "tru64", "Tru64");
4286   const char *sysname;
4287   char buf[2048];
4288 # ifdef HAVE_UNAME
4289   struct utsname uts;
4290 #endif /* UNAME */
4291
4292   bst->scroll_p = True;
4293   bst->y = bst->xgwa.height - bst->bottom_margin - bst->yoff
4294     - bst->font->ascent;
4295
4296   sysname = "127.0.0.1";
4297 # ifdef HAVE_UNAME
4298   {
4299     if (uname (&uts) >= 0)
4300       sysname = uts.nodename;
4301   }
4302 # endif /* !HAVE_UNAME */
4303
4304   sprintf (buf,
4305            "Compaq Tru64 UNIX V5.1B (Rev. 2650) (%.100s) console\n"
4306            "\n"
4307            "login: ",
4308            sysname);
4309   BSOD_TEXT (bst, LEFT, buf);
4310   BSOD_PAUSE (bst, 6000000);
4311
4312   BSOD_TEXT (bst, LEFT,
4313     "panic (cpu 0): trap: illegal instruction\n"
4314     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
4315     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
4316     "                                                                   \n"
4317     "DUMP: blocks available:  1571600\n"
4318     "DUMP: blocks wanted:      100802 (partial compressed dump) [OKAY]\n"
4319     "DUMP: Device     Disk Blocks Available\n"
4320     "DUMP: ------     ---------------------\n"
4321     "DUMP: 0x1300023  1182795 - 1571597 (of 1571598) [primary swap]\n"
4322     "DUMP.prom: Open: dev 0x5100041, block 2102016: SCSI 0 11 0 2 200 0 0\n"
4323     "DUMP: Writing header... [1024 bytes at dev 0x1300023, block 1571598]\n"
4324     "DUMP: Writing data");
4325
4326   {
4327     int i;
4328     int steps = 4 + (random() % 8);
4329     BSOD_CHAR_DELAY (bst, 1000000);
4330     for (i = 0; i < steps; i++)
4331       BSOD_TEXT (bst, LEFT, ".");
4332     BSOD_CHAR_DELAY (bst, 0);
4333     sprintf (buf, "[%dMB]\n", steps);
4334     BSOD_TEXT (bst, LEFT, buf);
4335   }
4336
4337   BSOD_TEXT (bst, LEFT,
4338     "DUMP: Writing header... [1024 bytes at dev 0x1300023, block 1571598]\n"
4339     "DUMP: crash dump complete.\n"
4340     "kernel inst fault=gentrap, ps=0x5, pc=0xfffffc0000593878, inst=0xaa\n"
4341     "                                                                   \n"
4342     "DUMP: second crash dump skipped: 'dump_savecnt' enforced.\n");
4343   BSOD_PAUSE (bst, 4000000);
4344
4345   BSOD_TEXT (bst, LEFT,
4346     "\n"
4347     "halted CPU 0\n"
4348     "\n"
4349     "halt code = 5\n"
4350     "HALT instruction executed\n"
4351     "PC = fffffc00005863b0\n");
4352   BSOD_PAUSE (bst, 3000000);
4353
4354   BSOD_TEXT (bst, LEFT,
4355     "\n"
4356     "CPU 0 booting\n"
4357     "\n"
4358     "\n"
4359     "\n");
4360
4361   XClearWindow(dpy, window);
4362   return bst;
4363 }
4364
4365
4366 /* MS-DOS, by jwz
4367  */
4368 static struct bsod_state *
4369 msdos (Display *dpy, Window window)
4370 {
4371   struct bsod_state *bst = make_bsod_state (dpy, window, "msdos", "MSDOS");
4372
4373   BSOD_CHAR_DELAY (bst, 10000);
4374   BSOD_TEXT (bst, LEFT, "C:\\WINDOWS>");
4375   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 8);
4376
4377   BSOD_CHAR_DELAY (bst, 200000);
4378   BSOD_TEXT (bst, LEFT, "dir a:");
4379   BSOD_PAUSE (bst, 1000000);
4380
4381   BSOD_CHAR_DELAY (bst, 10000);
4382   BSOD_TEXT (bst, LEFT, "\nNot ready reading drive A\nAbort, Retry, Fail?");
4383
4384   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 10);
4385   BSOD_CHAR_DELAY (bst, 200000);
4386   BSOD_TEXT (bst, LEFT, "f");
4387   BSOD_PAUSE (bst, 1000000);
4388
4389   BSOD_CHAR_DELAY (bst, 10000);
4390   BSOD_TEXT (bst, LEFT,
4391              "\n\n\nNot ready reading drive A\nAbort, Retry, Fail?");
4392
4393   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 10);
4394   BSOD_CHAR_DELAY (bst, 200000);
4395   BSOD_TEXT (bst, LEFT, "f");
4396   BSOD_PAUSE (bst, 1000000);
4397
4398   BSOD_CHAR_DELAY (bst, 10000);
4399   BSOD_TEXT (bst, LEFT, "\nVolume in drive A has no label\n\n"
4400                   "Not ready reading drive A\nAbort, Retry, Fail?");
4401
4402   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 12);
4403   BSOD_CHAR_DELAY (bst, 200000);
4404   BSOD_TEXT (bst, LEFT, "a");
4405   BSOD_PAUSE (bst, 1000000);
4406
4407   BSOD_CHAR_DELAY (bst, 10000);
4408   BSOD_TEXT (bst, LEFT, "\n\nC:\\WINDOWS>");
4409
4410   BSOD_CURSOR (bst, CURSOR_LINE, 200000, 999999);
4411
4412   XClearWindow(dpy, window);
4413   return bst;
4414 }
4415
4416
4417 /* nvidia, by jwz.
4418  *
4419  * This is what happens if an Nvidia card goes into some crazy text mode.
4420  * Most often seen on the second screen of a dual-head system when the
4421  * proper driver isn't loaded.
4422  */
4423 typedef struct { int fg; int bg; int bit; Bool blink; } nvcell;
4424
4425 static void
4426 nvspatter (nvcell *grid, int rows, int cols, int ncolors, int nbits,
4427            Bool fill_p)
4428 {
4429   int max = rows * cols;
4430   int from = fill_p ?   0 : random() % (max - 1);
4431   int len  = fill_p ? max : random() % (cols * 4);
4432   int to = from + len;
4433   int i;
4434   Bool noisy = ((random() % 4) == 0);
4435   Bool diag = (noisy || fill_p) ? 0 : ((random() % 4) == 0);
4436
4437   int fg = random() % ncolors;
4438   int bg = random() % ncolors;
4439   int blink = ((random() % 4) == 0);
4440   int bit = (random() % nbits);
4441
4442   if (to > max) to = max;
4443
4444   if (diag)
4445     {
4446       int src = random() % (rows * cols);
4447       int len2 = (cols / 2) - (random() % 5);
4448       int j = src;
4449       for (i = from; i < to; i++, j++)
4450         {
4451           if (j > src + len2 || j >= max)
4452             j = src;
4453           if (i >= max) abort();
4454           if (j >= max) abort();
4455           grid[j] = grid[i];
4456         }
4457     }
4458   else
4459     for (i = from; i < to; i++)
4460       {
4461         nvcell *cell = &grid[i];
4462         cell->fg = fg;
4463         cell->bg = bg;
4464         cell->bit = bit;
4465         cell->blink = blink;
4466
4467         if (noisy)
4468           {
4469             fg = random() % ncolors;
4470             bg = random() % ncolors;
4471             blink = ((random() % 8) == 0);
4472           }
4473       }
4474 }
4475
4476 typedef struct {
4477   struct bsod_state *bst;
4478   GC gc1;
4479   Pixmap bits[5];
4480   int rows, cols;
4481   int cellw, cellh;
4482   nvcell *grid;
4483   int ncolors;
4484   unsigned long colors[256];
4485   int tick;
4486 } nvstate;
4487
4488
4489 static void
4490 nvidia_free (struct bsod_state *bst)
4491 {
4492   nvstate *nvs = (nvstate *) bst->closure;
4493   int i;
4494   XFreeColors (bst->dpy, bst->xgwa.colormap, nvs->colors, nvs->ncolors, 0);
4495   for (i = 0; i < countof(nvs->bits); i++)
4496     XFreePixmap (bst->dpy, nvs->bits[i]);
4497   XFreeGC (bst->dpy, nvs->gc1);
4498   free (nvs->grid);
4499   free (nvs);
4500 }
4501
4502 static int
4503 nvidia_draw (struct bsod_state *bst)
4504 {
4505   nvstate *nvs = (nvstate *) bst->closure;
4506   int x, y;
4507
4508   for (y = 0; y < nvs->rows; y++)
4509     for (x = 0; x < nvs->cols; x++)
4510       {
4511         nvcell *cell = &nvs->grid[y * nvs->cols + x];
4512         unsigned long fg = nvs->colors[cell->fg];
4513         unsigned long bg = nvs->colors[cell->bg];
4514         Bool flip = cell->blink && (nvs->tick & 1);
4515         XSetForeground (bst->dpy, bst->gc, flip ? fg : bg);
4516         XSetBackground (bst->dpy, bst->gc, flip ? bg : fg);
4517         XCopyPlane (bst->dpy, nvs->bits[cell->bit], bst->window, bst->gc,
4518                     0, 0, nvs->cellw, nvs->cellh,
4519                     x * nvs->cellw, y * nvs->cellh, 1L);
4520       }
4521
4522   nvs->tick++;
4523   if ((random() % 5) == 0)    /* change the display */
4524     nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors,
4525                countof(nvs->bits), False);
4526
4527   return 250000;
4528 }
4529
4530
4531 static struct bsod_state *
4532 nvidia (Display *dpy, Window window)
4533 {
4534   struct bsod_state *bst = make_bsod_state (dpy, window, "nvidia", "nVidia");
4535   nvstate *nvs = (nvstate *) calloc (1, sizeof (*nvs));
4536
4537   XGCValues gcv;
4538   int i;
4539
4540   nvs->bst = bst;
4541   bst->closure = nvs;
4542   bst->draw_cb = nvidia_draw;
4543   bst->free_cb = nvidia_free;
4544
4545   nvs->cols = 80;
4546   nvs->rows = 25;
4547   nvs->cellw = bst->xgwa.width  / nvs->cols;
4548   nvs->cellh = bst->xgwa.height / nvs->rows;
4549   if (nvs->cellw < 8 || nvs->cellh < 18)
4550     nvs->cellw = 8, nvs->cellh = 18;
4551   nvs->cols = (bst->xgwa.width  / nvs->cellw) + 1;
4552   nvs->rows = (bst->xgwa.height / nvs->cellh) + 1;
4553
4554   nvs->grid = (nvcell *) calloc (sizeof(*nvs->grid), nvs->rows * nvs->cols);
4555
4556   /* Allocate colors
4557    */
4558   nvs->ncolors = 16;
4559   for (i = 0; i < nvs->ncolors; i++)
4560     {
4561       XColor c;
4562       c.red   = random() & 0xFFFF;
4563       c.green = random() & 0xFFFF;
4564       c.blue  = random() & 0xFFFF;
4565       c.flags = DoRed|DoGreen|DoBlue;
4566       XAllocColor (dpy, bst->xgwa.colormap, &c);
4567       nvs->colors[i] = c.pixel;
4568     }
4569
4570   /* Construct corrupted character bitmaps
4571    */
4572   for (i = 0; i < countof(nvs->bits); i++)
4573     {
4574       int j;
4575
4576       nvs->bits[i] = XCreatePixmap (dpy, window, nvs->cellw, nvs->cellh, 1);
4577       if (!nvs->gc1) nvs->gc1 = XCreateGC (dpy, nvs->bits[i], 0, &gcv);
4578
4579       XSetForeground (dpy, nvs->gc1, 0);
4580       XFillRectangle (dpy, nvs->bits[i], nvs->gc1, 0, 0,
4581                       nvs->cellw, nvs->cellh);
4582       XSetForeground (dpy, nvs->gc1, 1);
4583
4584       if ((random() % 40) != 0)
4585         for (j = 0; j < ((nvs->cellw * nvs->cellh) / 16); j++)
4586           XFillRectangle (dpy, nvs->bits[i], nvs->gc1,
4587                           (random() % (nvs->cellw-2)) & ~1,
4588                           (random() % (nvs->cellh-2)) & ~1,
4589                           2, 2);
4590     }
4591
4592   /* Randomize the grid
4593    */
4594   nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors,
4595              countof(nvs->bits), True);
4596   for (i = 0; i < 20; i++)
4597     nvspatter (nvs->grid, nvs->rows, nvs->cols, nvs->ncolors,
4598                countof(nvs->bits), False);
4599
4600   return bst;
4601 }
4602
4603
4604 /*
4605  * Simulate various Apple ][ crashes. The memory map encouraged many programs
4606  * to use the primary hi-res video page for various storage, and the secondary
4607  * hi-res page for active display. When it crashed into Applesoft or the
4608  * monitor, it would revert to the primary page and you'd see memory garbage on
4609  * the screen. Also, it was common for copy-protected games to use the primary
4610  * text page for important code, because that made it really hard to
4611  * reverse-engineer them. The result often looked like what this generates.
4612  *
4613  * The Apple ][ logic and video hardware is in apple2.c. The TV is emulated by
4614  * analogtv.c for maximum realism
4615  *
4616  * Trevor Blackwell <tlb@tlb.org>
4617  */
4618
4619 static const char * const apple2_basic_errors[]={
4620   "BREAK",
4621   "NEXT WITHOUT FOR",
4622   "SYNTAX ERROR",
4623   "RETURN WITHOUT GOSUB",
4624   "ILLEGAL QUANTITY",
4625   "OVERFLOW",
4626   "OUT OF MEMORY",
4627   "BAD SUBSCRIPT ERROR",
4628   "DIVISION BY ZERO",
4629   "STRING TOO LONG",
4630   "FORMULA TOO COMPLEX",
4631   "UNDEF'D FUNCTION",
4632   "OUT OF DATA"
4633 #if 0
4634   ,
4635   "DEFAULT ARGUMENTS ARE NOT ALLOWED IN DECLARATION OF FRIEND "
4636   "TEMPLATE SPECIALIZATION"
4637 #endif
4638
4639 };
4640 static const char * const apple2_dos_errors[]={
4641   "VOLUME MISMATCH",
4642   "I/O ERROR",
4643   "DISK FULL",
4644   "NO BUFFERS AVAILABLE",
4645   "PROGRAM TOO LARGE",
4646 };
4647
4648 static void a2controller_crash(apple2_sim_t *sim, int *stepno,
4649                                double *next_actiontime)
4650 {
4651   apple2_state_t *st=sim->st;
4652   char *s;
4653   int i;
4654
4655   struct mydata {
4656     int fillptr;
4657     int fillbyte;
4658   } *mine;
4659
4660   if (!sim->controller_data)
4661     sim->controller_data = calloc(sizeof(struct mydata),1);
4662   mine=(struct mydata *) sim->controller_data;
4663
4664   switch(*stepno) {
4665   case 0:
4666
4667     a2_init_memory_active(sim);
4668     sim->dec->powerup = 1000.0;
4669
4670     if (random()%3==0) {
4671       st->gr_mode=0;
4672       *next_actiontime+=0.4;
4673       *stepno=100;
4674     }
4675     else if (random()%4==0) {
4676       st->gr_mode=A2_GR_LORES;
4677       if (random()%3==0) st->gr_mode |= A2_GR_FULL;
4678       *next_actiontime+=0.4;
4679       *stepno=100;
4680     }
4681     else if (random()%2==0) {
4682       st->gr_mode=A2_GR_HIRES;
4683       *stepno=300;
4684     }
4685     else {
4686       st->gr_mode=A2_GR_HIRES;
4687       *next_actiontime+=0.4;
4688       *stepno=100;
4689     }
4690     break;
4691
4692   case 100:
4693     /* An illegal instruction or a reset caused it to drop into the
4694        assembly language monitor, where you could disassemble code & view
4695        data in hex. */
4696     if (random()%3==0) {
4697       char ibytes[128];
4698       char itext[128];
4699       int addr=0xd000+random()%0x3000;
4700       sprintf(ibytes,
4701               "%02X",random()%0xff);
4702       sprintf(itext,
4703               "???");
4704       sprintf(sim->printing_buf,
4705               "\n\n"
4706               "%04X: %-15s %s\n"
4707               " A=%02X X=%02X Y=%02X S=%02X F=%02X\n"
4708               "*",
4709               addr,ibytes,itext,
4710               random()%0xff, random()%0xff,
4711               random()%0xff, random()%0xff,
4712               random()%0xff);
4713       sim->printing=sim->printing_buf;
4714       a2_goto(st,23,1);
4715       if (st->gr_mode) {
4716         *stepno=180;
4717       } else {
4718         *stepno=200;
4719       }
4720       sim->prompt='*';
4721       *next_actiontime += 2.0 + (random()%1000)*0.0002;
4722     }
4723     else {
4724       /* Lots of programs had at least their main functionality in
4725          Applesoft Basic, which had a lot of limits (memory, string
4726          length, etc) and would sometimes crash unexpectedly. */
4727       sprintf(sim->printing_buf,
4728               "\n"
4729               "\n"
4730               "\n"
4731               "?%s IN %d\n"
4732               "\001]",
4733               apple2_basic_errors[random() %
4734                                   (sizeof(apple2_basic_errors)
4735                                    /sizeof(char *))],
4736               (1000*(random()%(random()%59+1)) +
4737                100*(random()%(random()%9+1)) +
4738                5*(random()%(random()%199+1)) +
4739                1*(random()%(random()%(random()%2+1)+1))));
4740       sim->printing=sim->printing_buf;
4741       a2_goto(st,23,1);
4742       *stepno=110;
4743       sim->prompt=']';
4744       *next_actiontime += 2.0 + (random()%1000)*0.0002;
4745     }
4746     break;
4747
4748   case 110:
4749     if (random()%3==0) {
4750       /* This was how you reset the Basic interpreter. The sort of
4751          incantation you'd have on a little piece of paper taped to the
4752          side of your machine */
4753       sim->typing="CALL -1370";
4754       *stepno=120;
4755     }
4756     else if (random()%2==0) {
4757       sim->typing="CATALOG\n";
4758       *stepno=170;
4759     }
4760     else {
4761       *next_actiontime+=1.0;
4762       *stepno=999;
4763     }
4764     break;
4765
4766   case 120:
4767     *stepno=130;
4768     *next_actiontime += 0.5;
4769     break;
4770
4771   case 130:
4772     st->gr_mode=0;
4773     a2_cls(st);
4774     a2_goto(st,0,16);
4775     for (s="APPLE ]["; *s; s++) a2_printc(st,*s);
4776     a2_goto(st,23,0);
4777     a2_printc(st,']');
4778     *next_actiontime+=1.0;
4779     *stepno=999;
4780     break;
4781
4782   case 170:
4783     if (random()%50==0) {
4784       sprintf(sim->printing_buf,
4785               "\nDISK VOLUME 254\n\n"
4786               " A 002 HELLO\n"
4787               "\n"
4788               "]");
4789       sim->printing=sim->printing_buf;
4790     }
4791     else {
4792       sprintf(sim->printing_buf,"\n?%s\n]",
4793               apple2_dos_errors[random()%
4794                                 (sizeof(apple2_dos_errors) /
4795                                  sizeof(char *))]);
4796       sim->printing=sim->printing_buf;
4797     }
4798     *stepno=999;
4799     *next_actiontime+=1.0;
4800     break;
4801
4802   case 180:
4803     if (random()%2==0) {
4804       /* This was how you went back to text mode in the monitor */
4805       sim->typing="FB4BG";
4806       *stepno=190;
4807     } else {
4808       *next_actiontime+=1.0;
4809       *stepno=999;
4810     }
4811     break;
4812
4813   case 190:
4814     st->gr_mode=0;
4815     a2_invalidate(st);
4816     a2_printc(st,'\n');
4817     a2_printc(st,'*');
4818     *stepno=200;
4819     *next_actiontime+=2.0;
4820     break;
4821
4822   case 200:
4823     /* This reset things into Basic */
4824     if (random()%2==0) {
4825       sim->typing="FAA6G";
4826       *stepno=120;
4827     }
4828     else {
4829       *stepno=999;
4830       *next_actiontime+=sim->delay;
4831     }
4832     break;
4833
4834   case 300:
4835     for (i=0; i<1500; i++) {
4836       a2_poke(st, mine->fillptr, mine->fillbyte);
4837       mine->fillptr++;
4838       mine->fillbyte = (mine->fillbyte+1)&0xff;
4839     }
4840     *next_actiontime += 0.08;
4841     /* When you hit c000, it changed video settings */
4842     if (mine->fillptr>=0xc000) {
4843       a2_invalidate(st);
4844       st->gr_mode=0;
4845     }
4846     /* And it seemed to reset around here, I dunno why */
4847     if (mine->fillptr>=0xcf00) *stepno=130;
4848     break;
4849
4850   case 999:
4851     break;
4852
4853   case A2CONTROLLER_FREE:
4854     free(mine);
4855     mine = 0;
4856     break;
4857   }
4858 }
4859
4860 static int
4861 a2_draw (struct bsod_state *bst)
4862 {
4863   apple2_sim_t *sim = (apple2_sim_t *) bst->closure;
4864   if (! sim) {
4865     sim = apple2_start (bst->dpy, bst->window, 9999999, a2controller_crash);
4866     bst->closure = sim;
4867   }
4868
4869   if (! apple2_one_frame (sim)) {
4870     bst->closure = 0;
4871   }
4872
4873   return 10000;
4874 }
4875
4876 static void
4877 a2_free (struct bsod_state *bst)
4878 {
4879   apple2_sim_t *sim = (apple2_sim_t *) bst->closure;
4880   if (sim) {
4881     sim->stepno = A2CONTROLLER_DONE;
4882     a2_draw (bst);              /* finish up */
4883     if (bst->closure) abort();  /* should have been freed by now */
4884   }
4885 }
4886
4887
4888 static struct bsod_state *
4889 apple2crash (Display *dpy, Window window)
4890 {
4891   struct bsod_state *bst = make_bsod_state (dpy, window, "apple2", "Apple2");
4892   bst->draw_cb = a2_draw;
4893   bst->free_cb = a2_free;
4894   return bst;
4895 }
4896
4897
4898 static void
4899 a2controller_ransomware(apple2_sim_t *sim, int *stepno,
4900                         double *next_actiontime)
4901 {
4902   apple2_state_t *st=sim->st;
4903
4904   struct mydata {
4905     const char *str;
4906     Bool bold_p;
4907   } *mine;
4908
4909   if (!sim->controller_data)
4910     sim->controller_data = calloc(sizeof(struct mydata),1);
4911   mine=(struct mydata *) sim->controller_data;
4912
4913   switch(*stepno) {
4914   case 0:
4915
4916     st->gr_mode |= A2_GR_FULL;
4917     a2_cls(st);
4918     a2_goto(st,0,16);
4919     a2_prints(st, "APPLE ][");
4920     a2_goto(st,2,0);
4921     *stepno = 10;
4922     *next_actiontime += 2;
4923     break;
4924
4925   case 10:
4926     a2_prints(st, "READY\n\n");
4927     *stepno = 11;
4928     *next_actiontime += 1;
4929     break;
4930
4931   case 11:
4932     a2_goto(st, 1, 0);
4933     *stepno = 12;
4934     mine->str =
4935       ("\n"
4936        " _____________________________________\n"
4937        "/                                     \\\n"
4938        "! OOPS YOUR FILES HAVE BEEN ENCRYPTED !\n"
4939        "!          ________________________   !\n"
4940        "!         !                        !  !\n"
4941        "!  [/--\\]   !  [ WHAT HAPPENED TO MY ] !  !\n"
4942        "!  [!]  [!]   !  [ COMPUTER? ]           !  !\n"
4943        "!  [!]  [!]   !                        !  !\n"
4944        "! [######]  !  [ CAN I RECOVER MY ]    !  !\n"
4945        "! [######]  !  [ FILES? ]              !  !\n"
4946        "! [######]  !                        !  !\n"
4947        "! [######]  !  [ HOW DO I PAY? ]       !  !\n"
4948        "!         !                        !  !\n"
4949        "!         !________________________!  !\n"
4950        "!                                     !\n"
4951        "!         BITCOIN ACCEPTED HERE       !\n"
4952        "\\_____________________________________/\n"
4953        "\n"
4954        "\n"
4955        "WAITING FOR BLOCKCHAIN..@\n"
4956        "\n"
4957        "PLEASE INSERT NEXT FLOPPY: "
4958        );
4959     break;
4960
4961   case 12:
4962     {
4963       char c = *mine->str;
4964       mine->str++;
4965
4966       if (c == 0)
4967         {
4968           *next_actiontime += 30;
4969           *stepno = 0;
4970         }
4971       else if (c == '[')
4972         mine->bold_p++;
4973       else if (c == ']')
4974         mine->bold_p--;
4975       else
4976         {
4977           if (c == '@')
4978             {
4979               c = '.';
4980               *next_actiontime += 2;
4981             }
4982
4983           if (mine->bold_p)
4984             c |= 0xC0;
4985           a2_printc_noscroll(st, c);
4986           if (c == '.')
4987             *next_actiontime += 1;
4988         }
4989     }
4990     break;
4991
4992   case A2CONTROLLER_FREE:
4993     return;
4994   }
4995 }
4996
4997
4998 static int
4999 a2_ransomware_draw (struct bsod_state *bst)
5000 {
5001   apple2_sim_t *sim = (apple2_sim_t *) bst->closure;
5002   if (! sim) {
5003     sim = apple2_start (bst->dpy, bst->window, 9999999,
5004                         a2controller_ransomware);
5005     bst->closure = sim;
5006   }
5007
5008   if (! apple2_one_frame (sim)) {
5009     bst->closure = 0;
5010   }
5011
5012   return 10000;
5013 }
5014
5015 static struct bsod_state *
5016 apple2ransomware (Display *dpy, Window window)
5017 {
5018   struct bsod_state *bst = make_bsod_state (dpy, window, "apple2", "Apple2");
5019   bst->draw_cb = a2_ransomware_draw;
5020   bst->free_cb = a2_free;
5021   return bst;
5022 }
5023
5024
5025
5026 /* A crash spotted on a cash machine circa 2006, by jwz.  I didn't note
5027    what model it was; probably a Tranax Mini-Bank 1000 or similar vintage.
5028  */
5029 static struct bsod_state *
5030 atm (Display *dpy, Window window)
5031 {
5032   struct bsod_state *bst = make_bsod_state (dpy, window, "atm", "ATM");
5033
5034   int pix_w, pix_h;
5035   int x, y, i = 0;
5036   float scale = 0.48;
5037   Pixmap mask = 0;
5038   Pixmap pixmap = image_data_to_pixmap (dpy, window,
5039                                         atm_png, sizeof(atm_png),
5040                                         &pix_w, &pix_h, &mask);
5041
5042   XClearWindow (dpy, window);
5043
5044   while (pix_w <= bst->xgwa.width  * scale &&
5045          pix_h <= bst->xgwa.height * scale)
5046     {
5047       pixmap = double_pixmap (dpy, bst->xgwa.visual, bst->xgwa.depth,
5048                               pixmap, pix_w, pix_h);
5049       mask = double_pixmap (dpy, bst->xgwa.visual, 1, mask, pix_w, pix_h);
5050       pix_w *= 2;
5051       pix_h *= 2;
5052       i++;
5053     }
5054
5055   x = (bst->xgwa.width  - pix_w) / 2;
5056   y = (bst->xgwa.height - pix_h) / 2;
5057   if (y < 0) y = 0;
5058
5059   if (i > 0)
5060     {
5061       int j;
5062       XSetForeground (dpy, bst->gc,
5063                       get_pixel_resource (dpy, bst->xgwa.colormap,
5064                                           "atm.background",
5065                                           "ATM.Background"));
5066       for (j = -1; j < pix_w; j += i+1)
5067         XDrawLine (bst->dpy, pixmap, bst->gc, j, 0, j, pix_h);
5068       for (j = -1; j < pix_h; j += i+1)
5069         XDrawLine (bst->dpy, pixmap, bst->gc, 0, j, pix_w, j);
5070     }
5071
5072   XSetClipMask (dpy, bst->gc, mask);
5073   XSetClipOrigin (dpy, bst->gc, x, y);
5074   XCopyArea (dpy, pixmap, window, bst->gc, 0, 0, pix_w, pix_h, x, y);
5075
5076   XFreePixmap (dpy, pixmap);
5077   XFreePixmap (dpy, mask);
5078
5079   return bst;
5080 }
5081
5082
5083 /* An Android phone boot loader, by jwz.
5084  */
5085 static struct bsod_state *
5086 android (Display *dpy, Window window)
5087 {
5088   struct bsod_state *bst = make_bsod_state (dpy, window, "android", "Android");
5089
5090   unsigned long bg = get_pixel_resource (dpy, bst->xgwa.colormap,
5091                                          "android.background",
5092                                          "Android.Background");
5093   unsigned long fg = get_pixel_resource (dpy, bst->xgwa.colormap,
5094                                          "android.foreground",
5095                                          "Android.Foreground");
5096   unsigned long c1 = get_pixel_resource (dpy, bst->xgwa.colormap,
5097                                          "android.color1",
5098                                          "Android.Foreground");
5099   unsigned long c2 = get_pixel_resource (dpy, bst->xgwa.colormap,
5100                                          "android.color2",
5101                                          "Android.Foreground");
5102   unsigned long c3 = get_pixel_resource (dpy, bst->xgwa.colormap,
5103                                          "android.color3",
5104                                          "Android.Foreground");
5105   unsigned long c4 = get_pixel_resource (dpy, bst->xgwa.colormap,
5106                                          "android.color4",
5107                                          "Android.Foreground");
5108   unsigned long c5 = get_pixel_resource (dpy, bst->xgwa.colormap,
5109                                          "android.color5",
5110                                          "Android.Foreground");
5111   unsigned long c6 = get_pixel_resource (dpy, bst->xgwa.colormap,
5112                                          "android.color6",
5113                                          "Android.Foreground");
5114   unsigned long c7 = get_pixel_resource (dpy, bst->xgwa.colormap,
5115                                          "android.color7",
5116                                          "Android.Foreground");
5117
5118   const char *lines0[] = {
5119     "Calculating... please wait\n",
5120     "osbl:     0x499DF907\n",
5121     "amss:     0x73162409\n",
5122     "hboot:    0xE46C3327\n",
5123     "boot:     0xBA570E7A\n",
5124     "recovery: 0xC8BBA213\n",
5125     "system:   0x87C3B1F0\n",
5126     "\n",
5127     "Press power key to go back.\n",
5128   };
5129
5130   const char *lines1[] = {
5131     "Checking SD card update...\n",
5132     "",
5133     "  SD Checking...\n",
5134     "  Failed to open zipfile\n",
5135     "  loading preload_content...\n",
5136     "  [Caution] Preload Content Not Found\n",
5137     "  loading HTCUpdateZipName image...\n",
5138     "",
5139     "  Checking...[PG46IMG.zip]\n",
5140     "Please plug off USB\n",
5141   };
5142
5143   const char *lines2[] = {
5144     "  SD Checking...\n",
5145     "  Loading...[PK76DIAG.zip]\n",
5146     "  No image!\n",
5147     "  Loading...[PK76DIAG.nbh]\n",
5148     "  No image or wrong image!\n",
5149     "  Loading...[PK76IMG.zip]\n",
5150     "  No image!\n",
5151     "  Loading...[PK76IMG.nbh]\n",
5152     "  No image or wrong image!\n",
5153     "  Loading...[PK76IMG.tar]\n",
5154     "  No image!\n",
5155     "  Loading...[PK76IMG.aes]\n",
5156     "  No image!\n",
5157     "  Loading...[PK76IMG.enc]\n",
5158     "  No image!\n",
5159   };
5160
5161   int cw = (bst->font->per_char
5162             ? bst->font->per_char['n'-bst->font->min_char_or_byte2].width
5163             : bst->font->min_bounds.width);
5164   int line_height = bst->font->ascent + bst->font->descent;
5165
5166   int state = 0;
5167
5168   Pixmap pixmap = 0, mask = 0;
5169   int pix_w = 0, pix_h = 0;
5170
5171   pixmap = image_data_to_pixmap (dpy, window, 
5172                                  android_png, sizeof(android_png),
5173                                  &pix_w, &pix_h, &mask);
5174   if (! pixmap) abort();
5175   {
5176     int i, n = 0;
5177     if (bst->xgwa.width > 2560) n++;  /* Retina displays */
5178     for (i = 0; i < n; i++)
5179       {
5180         pixmap = double_pixmap (dpy, bst->xgwa.visual, bst->xgwa.depth,
5181                                 pixmap, pix_w, pix_h);
5182         mask = double_pixmap (dpy, bst->xgwa.visual, 1,
5183                               mask, pix_w, pix_h);
5184         pix_w *= 2;
5185         pix_h *= 2;
5186       }
5187   }
5188   bst->pixmap = pixmap;
5189   bst->mask = mask;
5190
5191   bst->left_margin = (bst->xgwa.width - (cw * 40)) / 2;
5192   if (bst->left_margin < 0) bst->left_margin = 0;
5193
5194   while (1) {
5195     unsigned long delay =
5196       ((state == 0 ||
5197         state == countof(lines0) ||
5198         state == countof(lines0) + countof(lines1) ||
5199         state == countof(lines0) + countof(lines1) + countof(lines2))
5200                            ? 10000 : 0);
5201     BSOD_LINE_DELAY (bst, delay);
5202
5203     if (state <= countof(lines0) + countof(lines1) + countof(lines2))
5204       {
5205         BSOD_COLOR (bst, bg, bg);
5206         BSOD_RECT (bst, True, 0, 0, bst->xgwa.width, bst->xgwa.height);
5207         BSOD_COLOR (bst, bg, c1);
5208         BSOD_MOVETO (bst, bst->left_margin + bst->xoff,
5209                      bst->top_margin + bst->yoff + line_height);
5210         BSOD_TEXT (bst, LEFT, "*** UNLOCKED ***\n");
5211         BSOD_COLOR (bst, c2, bg);
5212         BSOD_TEXT (bst, LEFT,
5213                    "PRIMOU PVT SHIP S-OFF RL\n"
5214                    "HBOOT-1.17.0000\n"
5215                    "CPLD-None\n"
5216                    "MICROP-None\n"
5217                    "RADIO-3831.17.00.23_2\n"
5218                    "eMMC-bootmode: disabled\n"
5219                    "CPU-bootmode : disabled\n"
5220                    "HW Secure boot: enabled\n"
5221                    "MODEM PATH : OFF\n"
5222                    "May 15 2012, 10:28:15\n"
5223                    "\n");
5224         BSOD_COLOR (bst, bg, c3);
5225
5226         if (pixmap)
5227           {
5228             int x = (bst->xgwa.width - pix_w) / 2;
5229             int y = bst->xgwa.height - bst->yoff - pix_h;
5230             BSOD_PIXMAP (bst, 0, 0, pix_w, pix_h, x, y);
5231           }
5232       }
5233
5234     if (state == countof(lines0) ||
5235         state == countof(lines0) + countof(lines1) ||
5236         state == countof(lines0) + countof(lines1) + countof(lines2))
5237       {
5238         BSOD_TEXT (bst, LEFT, "HBOOT USB\n");
5239         BSOD_COLOR (bst, c4, bg);
5240         BSOD_TEXT (bst, LEFT,
5241                    "\n"
5242                    "<VOL UP> to previous item\n"
5243                    "<VOL DOWN> to next item\n"
5244                    "<POWER> to select item\n"
5245                    "\n");
5246         BSOD_COLOR (bst, c5, bg); BSOD_TEXT (bst, LEFT, "FASTBOOT\n");
5247         BSOD_COLOR (bst, c6, bg); BSOD_TEXT (bst, LEFT, "RECOVERY\n");
5248         BSOD_COLOR (bst, c7, bg); BSOD_TEXT (bst, LEFT, "FACTORY RESET\n");
5249         BSOD_COLOR (bst, c3, bg); BSOD_TEXT (bst, LEFT, "SIMLOCK\n");
5250         BSOD_COLOR (bst, bg, c3); BSOD_TEXT (bst, LEFT, "HBOOT USB\n");
5251         BSOD_COLOR (bst, fg, bg); BSOD_TEXT (bst, LEFT, "IMAGE CRC\n");
5252         BSOD_COLOR (bst, c3, bg); BSOD_TEXT (bst, LEFT, "SHOW BARCODE\n");
5253         BSOD_PAUSE (bst, 3000000);
5254       }
5255     else if (state < countof(lines0))
5256       {
5257         BSOD_TEXT (bst, LEFT, "IMAGE CRC\n\n");
5258         BSOD_COLOR (bst, c5, bg);
5259         {
5260           int i;
5261           for (i = 0; i <= state; i++) {
5262             const char *s = lines0[i];
5263             BSOD_COLOR (bst, (strchr(s, ':') ? c7 : c3), bg);
5264             BSOD_TEXT (bst, LEFT, s);
5265           }
5266         }
5267         BSOD_PAUSE (bst, 500000);
5268         if (state == countof(lines0)-1)
5269           BSOD_PAUSE (bst, 2000000);
5270       }
5271     else if (state < countof(lines0) + countof(lines1))
5272       {
5273         BSOD_TEXT (bst, LEFT, "HBOOT\n\n");
5274         BSOD_COLOR (bst, c5, bg);
5275         {
5276           int i;
5277           for (i = countof(lines0); i <= state; i++) {
5278             const char *s = lines1[i - countof(lines0)];
5279             BSOD_COLOR (bst, (*s == ' ' ? c6 : c3), bg);
5280             BSOD_TEXT (bst, LEFT, s);
5281           }
5282         }
5283         BSOD_PAUSE (bst, 500000);
5284         if (state == countof(lines0) + countof(lines1) - 1)
5285           BSOD_PAUSE (bst, 2000000);
5286       }
5287     else if (state < countof(lines0) + countof(lines1) + countof(lines2))
5288       {
5289         BSOD_TEXT (bst, LEFT, "HBOOT USB\n\n");
5290         BSOD_COLOR (bst, c5, bg);
5291         {
5292           int i;
5293           for (i = countof(lines0) + countof(lines1); i <= state; i++) {
5294             const char *s = lines2[i - countof(lines0) - countof(lines1)];
5295             BSOD_COLOR (bst, (*s == ' ' ? c6 : c3), bg);
5296             BSOD_TEXT (bst, LEFT, s);
5297           }
5298         }
5299         BSOD_PAUSE (bst, 500000);
5300         if (state == countof(lines0) + countof(lines1) + countof(lines2)-1)
5301           BSOD_PAUSE (bst, 2000000);
5302       }
5303     else
5304       break;
5305
5306     state++;
5307   }
5308
5309   XClearWindow (dpy, window);
5310
5311   return bst;
5312 }
5313
5314
5315
5316
5317 /*****************************************************************************
5318  *****************************************************************************/
5319
5320
5321 static const struct {
5322   const char *name;
5323   struct bsod_state * (*fn) (Display *, Window);
5324 } all_modes[] = {
5325   { "Windows",          windows_31 },
5326   { "NT",               windows_nt },
5327   { "Win2K",            windows_other },
5328   { "Win10",            windows_10 },
5329   { "Ransomware",       windows_ransomware },
5330   { "Amiga",            amiga },
5331   { "Mac",              mac },
5332   { "MacsBug",          macsbug },
5333   { "Mac1",             mac1 },
5334   { "MacX",             macx },
5335   { "SCO",              sco },
5336   { "HVX",              hvx },
5337   { "HPPALinux",        hppa_linux },
5338   { "SparcLinux",       sparc_linux },
5339   { "BSD",              bsd },
5340   { "Atari",            atari },
5341 #ifndef HAVE_JWXYZ
5342   { "BlitDamage",       blitdamage },
5343 #endif
5344   { "Solaris",          sparc_solaris },
5345   { "Linux",            linux_fsck },
5346   { "HPUX",             hpux },
5347   { "OS390",            os390 },
5348   { "Tru64",            tru64 },
5349   { "VMS",              vms },
5350   { "OS2",              os2 },
5351   { "MSDOS",            msdos },
5352   { "Nvidia",           nvidia },
5353   { "Apple2",           apple2crash },
5354   { "ATM",              atm },
5355   { "GLaDOS",           glados },
5356   { "Android",          android },
5357   { "VMware",           vmware },
5358 };
5359
5360
5361 struct driver_state {
5362   const char *name;
5363   int only, which, next_one;
5364   int mode_duration;
5365   int delay_remaining;
5366   time_t start;
5367   Bool debug_p, cycle_p;
5368   struct bsod_state *bst;
5369 };
5370
5371
5372 static void
5373 hack_title (struct driver_state *dst)
5374 {
5375 # ifndef HAVE_JWXYZ
5376   char *oname = 0;
5377   XFetchName (dst->bst->dpy, dst->bst->window, &oname);
5378   if (oname && !strncmp (oname, "BSOD: ", 6)) {
5379     char *tail = oname + 4;
5380     char *s = strchr (tail+1, ':');
5381     char *nname;
5382     if (s) tail = s;
5383     nname = malloc (strlen (tail) + strlen (dst->name) + 20);
5384     sprintf (nname, "BSOD: %s%s", dst->name, tail);
5385     XStoreName (dst->bst->dpy, dst->bst->window, nname);
5386     free (nname);
5387   }
5388 # endif /* !HAVE_JWXYZ */
5389 }
5390
5391 static void *
5392 bsod_init (Display *dpy, Window window)
5393 {
5394   struct driver_state *dst = (struct driver_state *) calloc (1, sizeof(*dst));
5395   char *s;
5396
5397   dst->mode_duration = get_integer_resource (dpy, "delay", "Integer");
5398   if (dst->mode_duration < 3) dst->mode_duration = 3;
5399
5400   dst->debug_p = get_boolean_resource (dpy, "debug", "Boolean");
5401
5402   dst->only = -1;
5403   dst->next_one = -1;
5404   s = get_string_resource(dpy, "doOnly", "DoOnly");
5405   if (s && !strcasecmp (s, "cycle"))
5406     {
5407       dst->which = -1;
5408       dst->cycle_p = True;
5409     }
5410   else if (s && *s)
5411     {
5412       int count = countof(all_modes);
5413       for (dst->only = 0; dst->only < count; dst->only++)
5414         if (!strcasecmp (s, all_modes[dst->only].name))
5415           break;
5416       if (dst->only >= count)
5417         {
5418           fprintf (stderr, "%s: unknown -only mode: \"%s\"\n", progname, s);
5419           dst->only = -1;
5420         }
5421     }
5422   if (s) free (s);
5423
5424   dst->name = "none";
5425   dst->which = -1;
5426   return dst;
5427 }
5428
5429
5430 static unsigned long
5431 bsod_draw (Display *dpy, Window window, void *closure)
5432 {
5433   struct driver_state *dst = (struct driver_state *) closure;
5434   time_t now;
5435   int time_left;
5436
5437  AGAIN:
5438   now = time ((time_t *) 0);
5439   time_left = dst->start + dst->mode_duration - now;
5440
5441   if (dst->bst && dst->bst->img_loader)   /* still loading */
5442     {
5443       dst->bst->img_loader =
5444         load_image_async_simple (dst->bst->img_loader, 0, 0, 0, 0, 0);
5445       return 100000;
5446     }
5447
5448  DELAY_NOW:
5449   /* Rather than returning a multi-second delay from the draw() routine,
5450      meaning "don't call us again for N seconds", we quantize that down
5451      to 1/10th second intervals so that it's more responsive to
5452      rotate/reshape events.
5453    */
5454   if (dst->delay_remaining)
5455     {
5456       int inc = 10000;
5457       int this_delay = MIN (dst->delay_remaining, inc);
5458       dst->delay_remaining = MAX (0, dst->delay_remaining - inc);
5459       return this_delay;
5460     }
5461
5462   if (! dst->bst && time_left > 0)      /* run completed; wait out the delay */
5463     {
5464       if (dst->debug_p)
5465         fprintf (stderr, "%s: %s: %d left\n", progname, dst->name, time_left);
5466       dst->start = 0;
5467       if (time_left > 5) time_left = 5;  /* Boooored now */
5468       dst->delay_remaining = 1000000 * time_left;
5469     }
5470
5471   else if (dst->bst)                    /* sub-mode currently running */
5472     {
5473       int this_delay = -1;
5474
5475       if (time_left > 0)
5476         this_delay = bsod_pop (dst->bst);
5477
5478       /* XSync (dpy, False);  slows down char drawing too much on HAVE_JWXYZ */
5479
5480       if (this_delay == 0)
5481         goto AGAIN;                     /* no delay, not expired: stay here */
5482       else if (this_delay >= 0)
5483         {
5484           dst->delay_remaining = this_delay;    /* return; time to sleep */
5485           goto DELAY_NOW;
5486         }
5487       else
5488         {                               /* sub-mode run completed or expired */
5489           if (dst->debug_p)
5490             fprintf (stderr, "%s: %s: done\n", progname, dst->name);
5491           free_bsod_state (dst->bst);
5492           dst->bst = 0;
5493           return 0;
5494         }
5495     }
5496   else                                  /* launch a new sub-mode */
5497     {
5498       if (dst->next_one >= 0)
5499         dst->which = dst->next_one, dst->next_one = -1;
5500       else if (dst->cycle_p)
5501         dst->which = (dst->which + 1) % countof(all_modes);
5502       else if (dst->only >= 0)
5503         dst->which = dst->only;
5504       else
5505         {
5506           int count = countof(all_modes);
5507           int *enabled = (int *) calloc (sizeof(*enabled), count + 1);
5508           int nenabled = 0;
5509           int i;
5510
5511           for (i = 0; i < count; i++)
5512             {
5513               char name[100], class[100];
5514               sprintf (name,  "do%s", all_modes[i].name);
5515               sprintf (class, "Do%s", all_modes[i].name);
5516               if (get_boolean_resource (dpy, name, class))
5517                 enabled[nenabled++] = i;
5518             }
5519
5520           if (nenabled == 0)
5521             {
5522               fprintf (stderr, "%s: no display modes enabled?\n", progname);
5523               /* exit (-1); */
5524               dst->which = dst->only = 0;
5525             }
5526           else if (nenabled == 1)
5527             dst->which = enabled[0];
5528           else
5529             {
5530               i = dst->which;
5531               while (i == dst->which)
5532                 i = enabled[random() % nenabled];
5533               dst->which = i;
5534             }
5535           free (enabled);
5536         }
5537
5538       if (dst->debug_p)
5539         fprintf (stderr, "%s: %s: launch\n", progname,
5540                  all_modes[dst->which].name);
5541
5542       /* Run the mode setup routine...
5543        */
5544       if (dst->bst) abort();
5545       dst->name  = all_modes[dst->which].name;
5546       dst->bst   = all_modes[dst->which].fn (dpy, window);
5547       dst->start = (dst->bst ? time ((time_t *) 0) : 0);
5548
5549       /* Reset the structure run state to the beginning,
5550          and do some sanitization of the cursor position
5551          before the first run.
5552        */
5553       if (dst->bst)
5554         {
5555           if (dst->debug_p)
5556             fprintf (stderr, "%s: %s: queue size: %d (%d)\n", progname,
5557                      dst->name, dst->bst->pos, dst->bst->queue_size);
5558
5559           hack_title (dst);
5560           dst->bst->pos = 0;
5561           dst->bst->x = dst->bst->current_left =
5562             dst->bst->left_margin + dst->bst->xoff;
5563
5564           if (dst->bst->y < 
5565               dst->bst->top_margin + dst->bst->yoff + dst->bst->font->ascent)
5566             dst->bst->y =
5567               dst->bst->top_margin + dst->bst->yoff + dst->bst->font->ascent;
5568         }
5569     }
5570
5571   return 0;
5572 }
5573
5574
5575 static void
5576 bsod_reshape (Display *dpy, Window window, void *closure,
5577               unsigned int w, unsigned int h)
5578 {
5579   struct driver_state *dst = (struct driver_state *) closure;
5580
5581   if (dst->bst &&
5582       w == dst->bst->xgwa.width &&
5583       h == dst->bst->xgwa.height)
5584     return;
5585
5586   if (dst->debug_p)
5587     fprintf (stderr, "%s: %s: reshape reset\n", progname, dst->name);
5588
5589   /* just restart this mode and restart when the window is resized. */
5590   if (dst->bst)
5591     free_bsod_state (dst->bst);
5592   dst->bst = 0;
5593   dst->start = 0;
5594   dst->delay_remaining = 0;
5595   dst->next_one = dst->which;
5596   dst->name = "none";
5597   XClearWindow (dpy, window);
5598 }
5599
5600
5601 static Bool
5602 bsod_event (Display *dpy, Window window, void *closure, XEvent *event)
5603 {
5604   struct driver_state *dst = (struct driver_state *) closure;
5605   Bool reset_p = False;
5606
5607   /* pick a new mode and restart when mouse clicked, or certain keys typed. */
5608
5609   if (screenhack_event_helper (dpy, window, event))
5610     reset_p = True;
5611
5612   if (reset_p)
5613     {
5614       if (dst->debug_p)
5615         fprintf (stderr, "%s: %s: manual reset\n", progname, dst->name);
5616       if (dst->bst)
5617         free_bsod_state (dst->bst);
5618       dst->bst = 0;
5619       dst->start = 0;
5620       dst->delay_remaining = 0;
5621       dst->name = "none";
5622       XClearWindow (dpy, window);
5623       return True;
5624     }
5625   else
5626     return False;
5627 }
5628
5629
5630 static void
5631 bsod_free (Display *dpy, Window window, void *closure)
5632 {
5633   struct driver_state *dst = (struct driver_state *) closure;
5634   if (dst->bst)
5635     free_bsod_state (dst->bst);
5636   free (dst);
5637 }
5638
5639
5640 static const char *bsod_defaults [] = {
5641   "*delay:                 45",
5642   "*debug:                 False",
5643
5644   "*doOnly:                ",
5645   "*doWindows:             True",
5646   "*doNT:                  True",
5647   "*doWin2K:               True",
5648   "*doWin10:               True",
5649   "*doRansomware:          True",
5650   "*doAmiga:               True",
5651   "*doMac:                 True",
5652   "*doMacsBug:             True",
5653   "*doMac1:                True",
5654   "*doMacX:                True",
5655   "*doSCO:                 True",
5656   "*doAtari:               False",      /* boring */
5657   "*doBSD:                 False",      /* boring */
5658   "*doLinux:               True",
5659   "*doSparcLinux:          False",      /* boring */
5660   "*doHPPALinux:           True",
5661   "*doBlitDamage:          True",
5662   "*doSolaris:             True",
5663   "*doHPUX:                True",
5664   "*doTru64:               True",
5665   "*doApple2:              True",
5666   "*doOS390:               True",
5667   "*doVMS:                 True",
5668   "*doHVX:                 True",
5669   "*doMSDOS:               True",
5670   "*doOS2:                 True",
5671   "*doNvidia:              True",
5672   "*doATM:                 True",
5673   "*doGLaDOS:              True",
5674   "*doAndroid:             True",
5675   "*doVMware:              True",
5676
5677   ".foreground:            White",
5678   ".background:            Black",
5679
5680   ".windows.foreground:    White",
5681   ".windows.background:    #0000AA",    /* EGA color 0x01. */
5682
5683   ".nt.foreground:         White",
5684   ".nt.background:         #0000AA",    /* EGA color 0x01. */
5685
5686   ".windowslh.foreground:  White",
5687   ".windowslh.background:  #AA0000",    /* EGA color 0x04. */
5688   ".windowslh.background2: #AAAAAA",    /* EGA color 0x07. */
5689
5690   ".win10.foreground:      White",
5691   ".win10.background:      #1070AA",
5692
5693   ".ransomware.foreground:   White",
5694   ".ransomware.background:   #841212",
5695   ".ransomware.foreground2:  Black",      /* ransom note */
5696   ".ransomware.background2:  White",
5697   ".ransomware.foreground3:  Black",      /* buttons */
5698   ".ransomware.background3:  #AAAAAA",
5699   ".ransomware.link:         #7BF9F6",
5700   ".ransomware.timerheader:  #BDBE02",
5701
5702
5703   ".glaDOS.foreground:     White",
5704   ".glaDOS.background:     #0000AA",    /* EGA color 0x01. */
5705
5706   ".amiga.foreground:      #FF0000",
5707   ".amiga.background:      Black",
5708   ".amiga.background2:     White",
5709
5710   ".mac.foreground:        #FFFFFF",
5711   ".mac.background:        Black",
5712
5713   ".atari.foreground:      Black",
5714   ".atari.background:      White",
5715
5716   ".macsbug.foreground:    Black",
5717   ".macsbug.background:    White",
5718   ".macsbug.borderColor:   #AAAAAA",
5719
5720   ".mac1.foreground:       Black",
5721   ".mac1.background:       White",
5722
5723   ".macx.foreground:       White",
5724   ".macx.textForeground:   White",
5725   ".macx.textBackground:   Black",
5726   ".macx.background:       #888888",
5727
5728   ".macinstall.barForeground: #C0C0C0",
5729   ".macinstall.barBackground: #888888",
5730
5731   ".sco.foreground:        White",
5732   ".sco.background:        Black",
5733
5734   ".hvx.foreground:        White",
5735   ".hvx.background:        Black",
5736
5737   ".linux.foreground:      White",
5738   ".linux.background:      Black",
5739
5740   ".hppalinux.foreground:  White",
5741   ".hppalinux.background:  Black",
5742
5743   ".sparclinux.foreground: White",
5744   ".sparclinux.background: Black",
5745
5746   ".bsd.foreground:        #c0c0c0",
5747   ".bsd.background:        Black",
5748
5749   ".solaris.foreground:    Black",
5750   ".solaris.background:    White",
5751
5752   ".hpux.foreground:       White",
5753   ".hpux.background:       Black",
5754
5755   ".os390.background:      Black",
5756   ".os390.foreground:      Red",
5757
5758   ".tru64.foreground:      White",
5759   ".tru64.background:      #0000AA",    /* EGA color 0x01. */
5760
5761   ".vms.foreground:        White",
5762   ".vms.background:        Black",
5763
5764   ".msdos.foreground:      White",
5765   ".msdos.background:      Black",
5766
5767   ".os2.foreground:        White",
5768   ".os2.background:        Black",
5769
5770   ".atm.foreground:        Black",
5771   ".atm.background:        #FF6600",
5772
5773   ".android.foreground:    Black",
5774   ".android.background:    White",
5775   ".android.color1:        #AA00AA", /* violet */
5776   ".android.color2:        #336633", /* green1 */
5777   ".android.color3:        #0000FF", /* blue */
5778   ".android.color4:        #CC7744", /* orange */
5779   ".android.color5:        #99AA55", /* green2 */
5780   ".android.color6:        #66AA33", /* green3 */
5781   ".android.color7:        #FF0000", /* red */
5782
5783   ".vmware.foreground:     White",
5784   ".vmware.foreground2:    Yellow",
5785   ".vmware.background:     #a700a8",    /* purple */
5786
5787   "*dontClearRoot:         True",
5788
5789   ANALOGTV_DEFAULTS
5790
5791 #ifdef HAVE_XSHM_EXTENSION
5792   "*useSHM:                True",
5793 #endif
5794
5795   "*fontB:                 ",
5796   "*fontC:                 ",
5797
5798 # if defined(USE_IPHONE)
5799
5800   "*font:                  PxPlus IBM VGA8 16, Courier-Bold 14",
5801   "*bigFont:               ",
5802
5803   ".mac.font:              Courier-Bold 18",
5804   ".macsbug.font:          Courier-Bold 8",
5805   ".macx.font:             Courier-Bold 14",
5806   ".macdisk.font:          Courier-Bold 14",
5807   ".macinstall.font:       Helvetica 12, Arial 12",
5808   ".macinstall.bigFont:    Helvetica 12, Arial 12",
5809   ".msdos.font:            PxPlus IBM VGA8 32, Courier-Bold 28",
5810   ".nt.font:               PxPlus IBM VGA8 12, Courier-Bold 10",
5811   ".win10.font:            Arial 12, Helvetica 12",
5812   ".win10.bigFont:         Arial 12, Helvetica 12",
5813   ".win10.fontB:           Arial 50, Helvetica 50",
5814   ".win10.fontC:           Arial 9, Helvetica 9",
5815
5816   /* The real Solaris font is ../OSX/Gallant19.bdf but I don't know how
5817      to convert that to a TTF, so let's use Luxi Mono instead. */
5818   ".solaris.font:          Luxi Mono 12, PxPlus IBM VGA8 12, Courier Bold 12",
5819
5820   /* "Arial" loads "ArialMT" but "Arial Bold" does not load "Arial-BoldMT"? */
5821   ".ransomware.font:         Arial 11, Helvetica 11",
5822   ".ransomware.fontB:        Arial 9, Helvetica 9",
5823   ".ransomware.fontC:        Arial Bold 11, Arial-BoldMT 11, Helvetica Bold 11",
5824
5825 # elif defined(HAVE_ANDROID)
5826
5827   "*font:                  PxPlus IBM VGA8 16",
5828   "*bigFont:               ",
5829
5830   ".mac.font:              -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
5831   ".macsbug.font:          -*-courier-bold-r-*-*-*-80-*-*-m-*-*-*",
5832   ".macx.font:             -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5833   ".macdisk.font:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5834   ".macinstall.font:       -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
5835   ".macinstall.bigFont:    -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
5836   ".msdos.font:            PxPlus IBM VGA8 32",
5837   ".nt.font:               PxPlus IBM VGA8 12",
5838   ".solaris.font:          Luxi Mono 12, PxPlus IBM VGA8 12, Courier Bold 12",
5839
5840   ".win10.font:            -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
5841   ".win10.bigFont:         -*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*",
5842   ".win10.fontB:           -*-helvetica-medium-r-*-*-*-500-*-*-*-*-*-*",
5843   ".win10.fontC:           -*-helvetica-medium-r-*-*-*-90-*-*-*-*-*-*",
5844
5845   ".ransomware.font:       -*-helvetica-medium-r-*-*-*-100-*-*-*-*-*-*",
5846   ".ransomware.fontB:      -*-helvetica-medium-r-*-*-*-80-*-*-*-*-*-*",
5847   ".ransomware.fontC:      -*-helvetica-bold-r-*-*-*-100-*-*-*-*-*-*",
5848
5849 # elif defined(HAVE_COCOA)
5850
5851   "*font:                  PxPlus IBM VGA8 8,  Courier Bold 9",
5852   "*bigFont:               PxPlus IBM VGA8 32, Courier Bold 24",
5853
5854   ".mac.font:              Monaco 10, Courier Bold 9",
5855   ".mac.bigFont:           Monaco 18, Courier Bold 18",
5856
5857   ".macsbug.font:          Monaco 10, Courier Bold 9",
5858   ".macsbug.bigFont:       Monaco 24, Courier Bold 24",
5859
5860   ".macx.font:             Courier Bold 9",
5861   ".macx.bigFont:          Courier Bold 14",
5862   ".macdisk.font:          Courier Bold 9",
5863   ".macdisk.bigFont:       Courier Bold 18",
5864   ".macinstall.font:       Helvetica 24, Arial 24",
5865   ".macinstall.bigFont:    Helvetica 24, Arial 24",
5866
5867   ".hvx.bigFont:           PxPlus IBM VGA8 16, Courier Bold 14",
5868   ".hppalinux.bigFont:     PxPlus IBM VGA8 16, Courier Bold 14",
5869   ".linux.bigFont:         PxPlus IBM VGA8 16, Courier Bold 14",
5870   ".hpux.bigFont:          PxPlus IBM VGA8 16, Courier Bold 14",
5871   ".msdos.font:            PxPlus IBM VGA8 16, Courier Bold 14",
5872   ".solaris.font:          Luxi Mono 12, PxPlus IBM VGA8 12, Courier Bold 12",
5873   ".solaris.bigFont:       Luxi Mono 16, PxPlus IBM VGA8 16, Courier Bold 14",
5874
5875   ".win10.font:            Arial 24, Helvetica 24",
5876   ".win10.bigFont:         Arial 24, Helvetica 24",
5877   ".win10.fontB:           Arial 100, Helvetica 100",
5878   ".win10.fontC:           Arial 16, Helvetica 16",
5879
5880   ".ransomware.font:         Arial 24, Helvetica 24",
5881   ".ransomware.bigFont:      Arial 24, Helvetica 24",
5882   ".ransomware.fontB:        Arial 16, Helvetica 16",
5883   ".ransomware.fontC:        Arial Bold 24, Helvetica Bold 24",
5884
5885 # else   /* X11 */
5886
5887   "*font:                  9x15bold",
5888   "*bigFont:               -*-courier-bold-r-*-*-*-180-*-*-m-*-*-*",
5889
5890   ".macsbug.font:          -*-courier-medium-r-*-*-*-80-*-*-m-*-*-*",
5891   ".macsbug.bigFont:       -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5892
5893   ".macdisk.font:          -*-courier-bold-r-*-*-*-80-*-*-m-*-*-*",
5894   ".macdisk.bigFont:       -*-courier-bold-r-*-*-*-100-*-*-m-*-*-*",
5895   ".macinstall.font:       -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5896   ".macinstall.bigFont:    -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5897
5898   ".sco.font:              -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5899   ".hvx.font:              -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5900   ".hppalinux.bigFont:     -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5901   ".sparclinux.bigFont:    -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5902
5903   /* Some systems might have this, but I'm not sure where it comes from: */
5904   /* ".bsd.font:           -*-vga-normal-r-*-*-*-120-*-*-c-*-*-*", */
5905   /* The fonts/misc/vga.pcf that comes with xdosemu has no XLFD name: */
5906   ".bsd.font:              vga",
5907   ".bsd.bigFont:           -*-vga-normal-r-*-*-*-220-*-*-c-*-*-*",
5908
5909   /* The original Solaris console font was:
5910      -sun-gallant-demi-r-normal-*-*-140-*-*-c-*-*-*
5911      Red Hat introduced Luxi Mono as its console font, which is similar
5912      to Gallant. X.Org includes it but Debian and Fedora do not. */
5913   ".solaris.font:          -*-luxi mono-medium-r-normal--*-140-*-*-m-*-*-*",
5914
5915   ".hpux.bigFont:          -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5916   ".os390.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5917   ".tru64.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5918   ".vms.bigFont:           -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5919   ".msdos.bigFont:         -*-courier-bold-r-*-*-*-140-*-*-m-*-*-*",
5920
5921   ".win10.font:            -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5922   ".win10.bigFont:         -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5923   ".win10.fontB:           -*-helvetica-medium-r-*-*-*-240-*-*-*-*-*-*",
5924   ".win10.fontC:           -*-helvetica-medium-r-*-*-*-140-*-*-*-*-*-*",
5925
5926   ".ransomware.font:       -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5927   ".ransomware.bigFont:    -*-helvetica-medium-r-*-*-*-180-*-*-*-*-*-*",
5928   ".ransomware.fontB:      -*-helvetica-medium-r-*-*-*-140-*-*-*-*-*-*",
5929   ".ransomware.fontC:      -*-helvetica-bold-r-*-*-*-180-*-*-*-*-*-*",
5930
5931
5932 # endif  /* X11 */
5933
5934   0
5935 };
5936
5937 static const XrmOptionDescRec bsod_options [] = {
5938   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
5939   { "-only",            ".doOnly",              XrmoptionSepArg, 0 },
5940   { "-debug",           ".debug",               XrmoptionNoArg,  "True"  },
5941   { "-windows",         ".doWindows",           XrmoptionNoArg,  "True"  },
5942   { "-no-windows",      ".doWindows",           XrmoptionNoArg,  "False" },
5943   { "-nt",              ".doNT",                XrmoptionNoArg,  "True"  },
5944   { "-no-nt",           ".doNT",                XrmoptionNoArg,  "False" },
5945   { "-2k",              ".doWin2K",             XrmoptionNoArg,  "True"  },
5946   { "-no-2k",           ".doWin2K",             XrmoptionNoArg,  "False" },
5947   { "-win10",           ".doWin10",             XrmoptionNoArg,  "True"  },
5948   { "-no-win10",        ".doWin10",             XrmoptionNoArg,  "False" },
5949   { "-ransomware",      ".doRansomware",        XrmoptionNoArg,  "True"  },
5950   { "-no-ransomware",   ".doRansomware",        XrmoptionNoArg,  "False" },
5951   { "-amiga",           ".doAmiga",             XrmoptionNoArg,  "True"  },
5952   { "-no-amiga",        ".doAmiga",             XrmoptionNoArg,  "False" },
5953   { "-mac",             ".doMac",               XrmoptionNoArg,  "True"  },
5954   { "-no-mac",          ".doMac",               XrmoptionNoArg,  "False" },
5955   { "-mac1",            ".doMac1",              XrmoptionNoArg,  "True"  },
5956   { "-no-mac1",         ".doMac1",              XrmoptionNoArg,  "False" },
5957   { "-macx",            ".doMacX",              XrmoptionNoArg,  "True"  },
5958   { "-no-macx",         ".doMacX",              XrmoptionNoArg,  "False" },
5959   { "-atari",           ".doAtari",             XrmoptionNoArg,  "True"  },
5960   { "-no-atari",        ".doAtari",             XrmoptionNoArg,  "False" },
5961   { "-macsbug",         ".doMacsBug",           XrmoptionNoArg,  "True"  },
5962   { "-no-macsbug",      ".doMacsBug",           XrmoptionNoArg,  "False" },
5963   { "-apple2",          ".doApple2",            XrmoptionNoArg,  "True"  },
5964   { "-no-apple2",       ".doApple2",            XrmoptionNoArg,  "False" },
5965   { "-sco",             ".doSCO",               XrmoptionNoArg,  "True"  },
5966   { "-no-sco",          ".doSCO",               XrmoptionNoArg,  "False" },
5967   { "-hvx",             ".doHVX",               XrmoptionNoArg,  "True"  },
5968   { "-no-hvx",          ".doHVX",               XrmoptionNoArg,  "False" },
5969   { "-bsd",             ".doBSD",               XrmoptionNoArg,  "True"  },
5970   { "-no-bsd",          ".doBSD",               XrmoptionNoArg,  "False" },
5971   { "-linux",           ".doLinux",             XrmoptionNoArg,  "True"  },
5972   { "-no-linux",        ".doLinux",             XrmoptionNoArg,  "False" },
5973   { "-hppalinux",       ".doHPPALinux",         XrmoptionNoArg,  "True"  },
5974   { "-no-hppalinux",    ".doHPPALinux",         XrmoptionNoArg,  "False" },
5975   { "-sparclinux",      ".doSparcLinux",        XrmoptionNoArg,  "True"  },
5976   { "-no-sparclinux",   ".doSparcLinux",        XrmoptionNoArg,  "False" },
5977   { "-blitdamage",      ".doBlitDamage",        XrmoptionNoArg,  "True"  },
5978   { "-no-blitdamage",   ".doBlitDamage",        XrmoptionNoArg,  "False" },
5979   { "-nvidia",          ".doNvidia",            XrmoptionNoArg,  "True"  },
5980   { "-no-nvidia",       ".doNvidia",            XrmoptionNoArg,  "False" },
5981   { "-solaris",         ".doSolaris",           XrmoptionNoArg,  "True"  },
5982   { "-no-solaris",      ".doSolaris",           XrmoptionNoArg,  "False" },
5983   { "-hpux",            ".doHPUX",              XrmoptionNoArg,  "True"  },
5984   { "-no-hpux",         ".doHPUX",              XrmoptionNoArg,  "False" },
5985   { "-os390",           ".doOS390",             XrmoptionNoArg,  "True"  },
5986   { "-no-os390",        ".doOS390",             XrmoptionNoArg,  "False" },
5987   { "-tru64",           ".doHPUX",              XrmoptionNoArg,  "True"  },
5988   { "-no-tru64",        ".doTru64",             XrmoptionNoArg,  "False" },
5989   { "-vms",             ".doVMS",               XrmoptionNoArg,  "True"  },
5990   { "-no-vms",          ".doVMS",               XrmoptionNoArg,  "False" },
5991   { "-msdos",           ".doMSDOS",             XrmoptionNoArg,  "True"  },
5992   { "-no-msdos",        ".doMSDOS",             XrmoptionNoArg,  "False" },
5993   { "-os2",             ".doOS2",               XrmoptionNoArg,  "True"  },
5994   { "-no-os2",          ".doOS2",               XrmoptionNoArg,  "False" },
5995   { "-atm",             ".doATM",               XrmoptionNoArg,  "True"  },
5996   { "-no-atm",          ".doATM",               XrmoptionNoArg,  "False" },
5997   { "-glados",          ".doGLaDOS",            XrmoptionNoArg,  "True"  },
5998   { "-no-glados",       ".doGLaDOS",            XrmoptionNoArg,  "False" },
5999   { "-android",         ".doAndroid",           XrmoptionNoArg,  "True"  },
6000   { "-no-android",      ".doAndroid",           XrmoptionNoArg,  "False" },
6001   { "-vmware",          ".doVMware",            XrmoptionNoArg,  "True"  },
6002   { "-no-vmware",       ".doVMware",            XrmoptionNoArg,  "False" },
6003   ANALOGTV_OPTIONS
6004   { 0, 0, 0, 0 }
6005 };
6006
6007
6008 XSCREENSAVER_MODULE ("BSOD", bsod)